diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..49b9991
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,38 @@
+################
+# Stage: Build #
+################
+
+FROM python:3.13-slim AS build
+
+WORKDIR /app
+
+# Export poetry dependencies to file
+RUN pip install --upgrade pip
+COPY poetry.lock pyproject.toml ./
+RUN pip install poetry poetry-plugin-export
+RUN poetry export --without-hashes --format requirements.txt --output /app/requirements.txt
+
+#####################
+# Stage: Production #
+#####################
+FROM python:3.13-slim AS prod
+
+# ENV PYTHONPATH=/app
+
+WORKDIR /app
+
+# Copy requirements from build stage, and install them
+COPY --from=build /app/requirements.txt .
+RUN pip install --upgrade pip
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY . .
+
+# Create a non-root user to run the web server
+RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
+USER appuser
+
+# Run server
+EXPOSE 8001
+# CMD ["gunicorn", "--bind", "0.0.0.0:8001", "main_package.app:app"]
+CMD ["uvicorn", "main_package.app:app", "--reload", "--host", "0.0.0.0", "--port", "8001"]
diff --git a/docker-build.sh b/docker-build.sh
new file mode 100755
index 0000000..d8c8c37
--- /dev/null
+++ b/docker-build.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+docker-compose build
+
+echo "Finish!"
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..24f0fea
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,9 @@
+services:
+ api:
+ build: .
+ image: app
+ ports:
+ - "8001:8001"
+ volumes:
+ - .:/app:ro
+ - ./datings.db:/app/datings.db:rw
diff --git a/docker-down.sh b/docker-down.sh
new file mode 100755
index 0000000..30a5bab
--- /dev/null
+++ b/docker-down.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+docker-compose down
+
+echo "Finish!"
diff --git a/docker-up.sh b/docker-up.sh
new file mode 100755
index 0000000..9e9eaf6
--- /dev/null
+++ b/docker-up.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+docker-compose up
+
+echo "Finish!"
diff --git a/LeraFoxQueen/main.py b/main_package/app.py
similarity index 72%
rename from LeraFoxQueen/main.py
rename to main_package/app.py
index b9c8b7a..d3283e2 100644
--- a/LeraFoxQueen/main.py
+++ b/main_package/app.py
@@ -5,9 +5,10 @@ import uuid
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request, HTTPException
-from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
+from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
+from fastapi_sitemap import SiteMap, URLInfo
from .database import create_tables, delete_tables
from .router import router as datings_router
@@ -44,6 +45,8 @@ app = FastAPI(
lifespan=lifespan, docs_url=None, redoc_url=None, openapi_url=settings.OPENAPI_URL
)
+favicon_path = "static/assets/img/favicons/favicon.ico"
+
templates = Jinja2Templates(directory="templates")
app.include_router(datings_router)
@@ -70,6 +73,11 @@ async def index(request: Request):
return response
+@app.get("/favicon.ico", include_in_schema=False)
+async def favicon():
+ return FileResponse(favicon_path)
+
+
@app.get("/robots.txt", response_class=PlainTextResponse)
def robots():
data = """User-agent: *\nAllow: /\nSitemap: /sitemap.xml"""
@@ -81,5 +89,31 @@ async def http_exception_handler(request, exc):
return JSONResponse(status_code=exc.status_code, content={"detail": exc.detail})
+sitemap = SiteMap(
+ app=app,
+ base_url="https://lerafoxqueen.ru",
+ static_dirs=["static", "docs"],
+ exclude_patterns=[
+ "^/api/",
+ "^/docs/",
+ "^/datings",
+ "^/api/",
+ "^/admin/",
+ ], # optional: exclude patterns
+ include_dynamic=True,
+ changefreq="daily",
+ priority_map={
+ "/": 1.0,
+ },
+ gzip=True, # optional: make a gz version too
+)
+
+sitemap.attach() # now GET /sitemap.xml is live
+
+# @sitemap.source
+# def extra_urls():
+# yield URLInfo("https://lerafoxqueen.ru/sitemap.xml")
+
+
if __name__ == "__main__":
- uvicorn.run(app, host="127.0.0.1", port=8001)
+ uvicorn.run(app, host="0.0.0.0", port=8001)
diff --git a/LeraFoxQueen/database.py b/main_package/database.py
similarity index 100%
rename from LeraFoxQueen/database.py
rename to main_package/database.py
diff --git a/LeraFoxQueen/repository.py b/main_package/repository.py
similarity index 100%
rename from LeraFoxQueen/repository.py
rename to main_package/repository.py
diff --git a/LeraFoxQueen/router.py b/main_package/router.py
similarity index 100%
rename from LeraFoxQueen/router.py
rename to main_package/router.py
diff --git a/LeraFoxQueen/schemas.py b/main_package/schemas.py
similarity index 100%
rename from LeraFoxQueen/schemas.py
rename to main_package/schemas.py
diff --git a/LeraFoxQueen/validity.py b/main_package/validity.py
similarity index 100%
rename from LeraFoxQueen/validity.py
rename to main_package/validity.py
diff --git a/pyproject.toml b/pyproject.toml
index 5e7a2d4..56f6859 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,5 +1,5 @@
[project]
-name = "LeraFoxQueen"
+name = "main_package"
version = "0.1.0"
description = ""
authors = [
@@ -13,6 +13,7 @@ dependencies = [
"hypercorn (>=0.17.3,<0.18.0)",
"unicorn (>=2.1.3,<3.0.0)",
"uvicorn (>=0.34.3,<0.35.0)",
+ "gunicorn (>=23.0.0,<24.0.0)",
"fastapi (>=0.115.12,<0.116.0)",
"aiosqlite (>=0.21.0,<0.22.0)",
"sqlalchemy (>=2.0.41,<3.0.0)",
@@ -29,8 +30,13 @@ dependencies = [
"sniffio (>=1.3.1,<2.0.0)",
"jinja2 (>=3.1.6,<4.0.0)",
"pydantic-settings (>=2.9.1,<3.0.0)",
+ "fastapi-sitemap (>=1.0.4,<2.0.0)",
]
package-mode = false
+packages = [{include = "main_package"}]
+
+[tool.poetry.requires-plugins]
+poetry-plugin-export = ">=1.8"
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
diff --git a/sitemap.xml b/sitemap.xml
new file mode 100644
index 0000000..3506b92
--- /dev/null
+++ b/sitemap.xml
@@ -0,0 +1,10 @@
+
+
- This page acts like a Demo page and a Testing page. -
- -- This page acts like a Demo page and a Testing page. -
- -- Testing page for issue #10 -
- -- This page acts like a Demo page and a Testing page. Here we are testing issue #20, solving a bug in which a scrollable dropdown inside a modal was closed when clicking on the scrollbar. -
- -- Testing page for issue #35 -
- -- Testing page for issue #59 -
- -- Testing page for issue #80 -
- -- Testing page for issue #83 -
- -- This page acts like a Demo page and a Testing page. -
- -- This page acts like a Demo page and a Testing page. -
- -- Testing page for issue #10 -
- -- This page acts like a Demo page and a Testing page. Here we are testing issue #20, solving a bug in which a scrollable dropdown inside a modal was closed when clicking on the scrollbar. -
- -- Testing page for issue #35 -
- -- Testing page for issue #59 -
- -- Testing page for issue #80 -
- -- Testing page for issue #83 -
- -`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 2. Add explicit cursor to indicate changed behavior.\n// 3. Prevent the text-decoration to be skipped.\n\nabbr[title] {\n text-decoration: underline dotted; // 1\n cursor: help; // 2\n text-decoration-skip-ink: none; // 3\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n color: var(--#{$prefix}highlight-color);\n background-color: var(--#{$prefix}highlight-bg);\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, 1));\n text-decoration: $link-decoration;\n\n &:hover {\n --#{$prefix}link-color-rgb: var(--#{$prefix}link-hover-color-rgb);\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: var(--#{$prefix}code-color);\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `