Improve template (#1)
- Created a README file - Added PyCharm/IntelliJ IDE run configuration - Squashed bugs related to: - Code style - Default Postgre database URL schema - Updated project dependencies Reviewed-on: #1 Co-authored-by: Ēriks K <git@72.lv> Co-committed-by: Ēriks K <git@72.lv>
This commit is contained in:
parent
0f01088e4f
commit
ef5da867a6
1
{{ cookiecutter.project_slug }}/.gitignore
vendored
1
{{ cookiecutter.project_slug }}/.gitignore
vendored
@ -176,3 +176,4 @@ dmypy.json
|
|||||||
.pytype/
|
.pytype/
|
||||||
cython_debug/
|
cython_debug/
|
||||||
cookiecutter.zip
|
cookiecutter.zip
|
||||||
|
envs.yml
|
||||||
|
8
{{ cookiecutter.project_slug }}/.idea/.gitignore
generated
vendored
Normal file
8
{{ cookiecutter.project_slug }}/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
6
{{ cookiecutter.project_slug }}/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
{{ cookiecutter.project_slug }}/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
{{ cookiecutter.project_slug }}/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
{{ cookiecutter.project_slug }}/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
7
{{ cookiecutter.project_slug }}/.idea/misc.xml
generated
Normal file
7
{{ cookiecutter.project_slug }}/.idea/misc.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3 ({{ cookiecutter.project_slug }})" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3 ({{ cookiecutter.project_slug }})" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
{{ cookiecutter.project_slug }}/.idea/modules.xml
generated
Normal file
8
{{ cookiecutter.project_slug }}/.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/{{ cookiecutter.project_slug }}.iml" filepath="$PROJECT_DIR$/.idea/{{ cookiecutter.project_slug }}.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
26
{{ cookiecutter.project_slug }}/.idea/runConfigurations/Create_migration.xml
generated
Normal file
26
{{ cookiecutter.project_slug }}/.idea/runConfigurations/Create_migration.xml
generated
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Create migration" type="PythonConfigurationType" factoryName="Python">
|
||||||
|
<module name="{{ cookiecutter.project_slug }}" />
|
||||||
|
<option name="ENV_FILES" value="" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<envs>
|
||||||
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
|
</envs>
|
||||||
|
<option name="SDK_HOME" value="" />
|
||||||
|
<option name="SDK_NAME" value="Python 3 ({{ cookiecutter.project_slug }})" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="IS_MODULE_SDK" value="false" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||||
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/venv/bin/aerich" />
|
||||||
|
<option name="PARAMETERS" value="migrate" />
|
||||||
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
|
<option name="MODULE_MODE" value="false" />
|
||||||
|
<option name="REDIRECT_INPUT" value="false" />
|
||||||
|
<option name="INPUT_FILE" value="" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
18
{{ cookiecutter.project_slug }}/.idea/runConfigurations/Run.xml
generated
Normal file
18
{{ cookiecutter.project_slug }}/.idea/runConfigurations/Run.xml
generated
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Run" type="Python.FastAPI">
|
||||||
|
<option name="file" value="$PROJECT_DIR$/service/api/main.py" />
|
||||||
|
<module name="{{ cookiecutter.project_slug }}" />
|
||||||
|
<option name="ENV_FILES" value="" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<option name="SDK_HOME" value="$PROJECT_DIR$/venv/bin/python" />
|
||||||
|
<option name="SDK_NAME" value="Python 3 ({{ cookiecutter.project_slug }})" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="IS_MODULE_SDK" value="false" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||||
|
<option name="launchJavascriptDebuger" value="false" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
26
{{ cookiecutter.project_slug }}/.idea/runConfigurations/Run_Migrations.xml
generated
Normal file
26
{{ cookiecutter.project_slug }}/.idea/runConfigurations/Run_Migrations.xml
generated
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Run Migrations" type="PythonConfigurationType" factoryName="Python">
|
||||||
|
<module name="{{ cookiecutter.project_slug }}" />
|
||||||
|
<option name="ENV_FILES" value="" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<envs>
|
||||||
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
|
</envs>
|
||||||
|
<option name="SDK_HOME" value="" />
|
||||||
|
<option name="SDK_NAME" value="Python 3 ({{ cookiecutter.project_slug }})" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="IS_MODULE_SDK" value="false" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||||
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/venv/bin/aerich" />
|
||||||
|
<option name="PARAMETERS" value="upgrade" />
|
||||||
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
|
<option name="MODULE_MODE" value="false" />
|
||||||
|
<option name="REDIRECT_INPUT" value="false" />
|
||||||
|
<option name="INPUT_FILE" value="" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
6
{{ cookiecutter.project_slug }}/.idea/vcs.xml
generated
Normal file
6
{{ cookiecutter.project_slug }}/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
14
{{ cookiecutter.project_slug }}/.idea/{{ cookiecutter.project_slug }}.iml
generated
Normal file
14
{{ cookiecutter.project_slug }}/.idea/{{ cookiecutter.project_slug }}.iml
generated
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.12 (project_slug)" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
<component name="PyDocumentationSettings">
|
||||||
|
<option name="format" value="PLAIN" />
|
||||||
|
<option name="myDocStringFormat" value="Plain" />
|
||||||
|
</component>
|
||||||
|
</module>
|
@ -1,13 +1,13 @@
|
|||||||
FROM python:3.12-alpine as python
|
FROM python:3.12-alpine AS python
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENV PYTHONUNBUFFERED 1
|
ARG ENVIRONMENT=local
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
ENV TZ="Europe/Riga"
|
ENV TZ="Europe/Riga"
|
||||||
|
|
||||||
COPY requirements /app/requirements
|
COPY requirements /app/requirements
|
||||||
RUN apk add libpq \
|
RUN apk add libpq \
|
||||||
poppler-utils zlib-dev \
|
poppler-utils zlib-dev \
|
||||||
# curl \
|
&& pip install --no-cache-dir --upgrade -r requirements/${ENVIRONMENT}.txt \
|
||||||
&& pip install --no-cache-dir --upgrade -r requirements/production.txt \
|
|
||||||
&& rm -rf /var/cache/apk/*
|
&& rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
COPY entrypoint.sh /entrypoint
|
COPY entrypoint.sh /entrypoint
|
||||||
@ -19,4 +19,4 @@ RUN chmod +x /entrypoint \
|
|||||||
EXPOSE 5000
|
EXPOSE 5000
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint"]
|
ENTRYPOINT ["/entrypoint"]
|
||||||
CMD ["uvicorn", "--workers", "2", "--proxy-headers", "--host", "0.0.0.0", "--port", "5000", "--forwarded-allow-ips=*", "service.main:app"]
|
CMD ["uvicorn", "--workers", "2", "--proxy-headers", "--host", "0.0.0.0", "--port", "5000", "--forwarded-allow-ips=*", "service.api.main:app"]
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
# `SERVICE_DATABASE_URL`
|
# `SERVICE_DATABASE_URL`
|
||||||
|
|
||||||
*Optional*, default value: `psql://{{ cookiecutter.project_slug }}:{{ cookiecutter.project_slug }}@postgres:5432/{{ cookiecutter.project_slug }}`
|
*Optional*, default value: `asyncpg://{{ cookiecutter.project_slug }}:{{ cookiecutter.project_slug }}@postgres:5432/{{ cookiecutter.project_slug }}`
|
||||||
|
|
||||||
# `SERVICE_TIMEZONE`
|
# `SERVICE_TIMEZONE`
|
||||||
|
|
||||||
|
37
{{ cookiecutter.project_slug }}/README.md
Normal file
37
{{ cookiecutter.project_slug }}/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Welcome to {{ cookiecutter.project_name }}
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
### 1. Install dependencies
|
||||||
|
#### Local virtual environment
|
||||||
|
```shell
|
||||||
|
python3 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r requirements/local.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Docker image
|
||||||
|
```shell
|
||||||
|
docker build -f Dockerfile --tag {{ cookiecutter.project_slug }} .
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Initial setup
|
||||||
|
#### Environment variables
|
||||||
|
Environment variables for the project are being read from the env.yml file:
|
||||||
|
- Copy example yml:
|
||||||
|
`cp envs.example.yml envs.yml`
|
||||||
|
- Adjust values as necessary
|
||||||
|
|
||||||
|
#### Initialize database
|
||||||
|
```shell
|
||||||
|
aerich init-db
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Migrate database
|
||||||
|
```shell
|
||||||
|
aerich upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create new database migration
|
||||||
|
```shell
|
||||||
|
aerich migrate
|
||||||
|
```
|
@ -7,13 +7,13 @@ service:
|
|||||||
token_expiration_days: 28
|
token_expiration_days: 28
|
||||||
cors_origins:
|
cors_origins:
|
||||||
- "http://localhost:5000"
|
- "http://localhost:5000"
|
||||||
- "https://example.com"
|
- "https://{{ cookiecutter.project_slug }}.xyz"
|
||||||
|
|
||||||
environment: "local"
|
environment: "local"
|
||||||
log_level: "DEBUG"
|
log_level: "DEBUG"
|
||||||
|
|
||||||
redis_url: "redis://redis:6379"
|
redis_url: "redis://redis:6379"
|
||||||
database_url: "psql://{{ cookiecutter.project_slug }}:{{ cookiecutter.project_slug }}@postgres:5432/{{ cookiecutter.project_slug }}"
|
database_url: "asyncpg://{{ cookiecutter.project_slug }}:{{ cookiecutter.project_slug }}@postgres:5432/{{ cookiecutter.project_slug }}"
|
||||||
|
|
||||||
timezone: "UTC"
|
timezone: "UTC"
|
||||||
sentry_url: null
|
sentry_url: null
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
fastapi==0.115.5 # https://github.com/tiangolo/fastapi
|
fastapi==0.115.12 # https://github.com/tiangolo/fastapi
|
||||||
uvicorn==0.32.1 # https://pypi.org/project/uvicorn/
|
uvicorn==0.34.0 # https://pypi.org/project/uvicorn/
|
||||||
|
|
||||||
pydantic[email]==2.10.2 # https://github.com/pydantic/pydantic
|
pydantic[email]==2.11.2 # https://github.com/pydantic/pydantic
|
||||||
pydantic-settings[yaml]==2.6.1 # https://github.com/pydantic/pydantic-settings/
|
pydantic-settings[yaml]==2.8.1 # https://github.com/pydantic/pydantic-settings/
|
||||||
|
|
||||||
tortoise-orm[accel,asyncpg]==0.22.1 # https://pypi.org/project/tortoise-orm/
|
tortoise-orm[accel,asyncpg]==0.24.2 # https://pypi.org/project/tortoise-orm/
|
||||||
aerich==0.7.2 # https://pypi.org/project/aerich/
|
aerich==0.8.2 # https://pypi.org/project/aerich/
|
||||||
|
|
||||||
setech==1.4.2 # https://pypi.org/project/setech/
|
setech==1.4.2 # https://pypi.org/project/setech/
|
||||||
|
|
||||||
python-multipart==0.0.18 # https://pypi.org/project/python-multipart/
|
python-multipart==0.0.20 # https://pypi.org/project/python-multipart/
|
||||||
email-validator==2.2.0 # https://pypi.org/project/email-validator/
|
email-validator==2.2.0 # https://pypi.org/project/email-validator/
|
||||||
|
|
||||||
|
|
||||||
tenacity==9.0.0 # https://pypi.org/project/tenacity/
|
tenacity==9.1.2 # https://pypi.org/project/tenacity/
|
||||||
pydantic==2.10.2 # https://pypi.org/project/pydantic/
|
pydantic==2.11.2 # https://pypi.org/project/pydantic/
|
||||||
#emails==0.6 # https://pypi.org/project/emails/
|
#emails==0.6 # https://pypi.org/project/emails/
|
||||||
|
|
||||||
python-jose[cryptography]==3.3 # https://pypi.org/project/python-jose/
|
python-jose[cryptography]==3.4.0 # https://pypi.org/project/python-jose/
|
||||||
passlib[bcrypt]==1.7.4 # https://pypi.org/project/passlib/
|
passlib[bcrypt]==1.7.4 # https://pypi.org/project/passlib/
|
||||||
bcrypt==4.2.1 # https://pypi.org/project/bcrypt/
|
bcrypt==4.3.0 # https://pypi.org/project/bcrypt/
|
||||||
# Pin bcrypt until passlib supports the latest
|
# Pin bcrypt until passlib supports the latest
|
||||||
pydantic-settings==2.6.1 # https://pypi.org/project/pydantic-settings/
|
pydantic-settings==2.8.1 # https://pypi.org/project/pydantic-settings/
|
||||||
|
|
||||||
asyncio==3.4.3
|
asyncio==3.4.3
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
-r base.txt
|
-r base.txt
|
||||||
|
|
||||||
uvicorn[standard]==0.32.1 # https://pypi.org/project/uvicorn/
|
uvicorn[standard]==0.34.0 # https://pypi.org/project/uvicorn/
|
||||||
|
|
||||||
black==24.10.0 # https://pypi.org/project/black/
|
black==25.1.0 # https://pypi.org/project/black/
|
||||||
isort==5.13.2 # https://pypi.org/project/isort/
|
isort==6.0.1 # https://pypi.org/project/isort/
|
||||||
pur==7.3.2 # https://pypi.org/project/pur/
|
pur==7.3.3 # https://pypi.org/project/pur/
|
||||||
pre-commit==4.0.1 # https://pypi.org/project/pre-commit/
|
pre-commit==4.2.0 # https://pypi.org/project/pre-commit/
|
||||||
flake8==7.1.1
|
flake8==7.2.0
|
||||||
|
|
||||||
pytest==8.3.3 # https://pypi.org/project/pytest/
|
pytest==8.3.5 # https://pypi.org/project/pytest/
|
||||||
coverage==7.6.8 # https://pypi.org/project/coverage/
|
coverage==7.8.0 # https://pypi.org/project/coverage/
|
||||||
|
|
||||||
mypy==1.13.0 # https://pypi.org/project/mypy/
|
mypy==1.15.0 # https://pypi.org/project/mypy/
|
||||||
types-python-jose==3.3.4.20240106 # https://pypi.org/project/types-python-jose/
|
types-python-jose==3.4.0.20250224 # https://pypi.org/project/types-python-jose/
|
||||||
types-passlib==1.7.7.20240819 # https://pypi.org/project/types-passlib/
|
types-passlib==1.7.7.20250401 # https://pypi.org/project/types-passlib/
|
||||||
types-PyYAML==6.0.12.20240917
|
types-PyYAML==6.0.12.20250402
|
||||||
types-Pygments==2.18.0.20240506
|
types-Pygments==2.19.0.20250305
|
||||||
types-colorama==0.4.15.20240311
|
types-colorama==0.4.15.20240311
|
||||||
types-decorator==5.1.8.20240310
|
types-decorator==5.2.0.20250324
|
||||||
types-six==1.16.21.20241105
|
types-six==1.17.0.20250403
|
||||||
types-ujson==5.10.0.20240515
|
types-ujson==5.10.0.20250326
|
||||||
|
|
||||||
settings-doc==4.3.1 # https://github.com/radeklat/settings-doc
|
settings-doc==4.3.2 # https://github.com/radeklat/settings-doc
|
||||||
ipython==8.30.0
|
ipython==9.0.2
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
-r base.txt
|
-r base.txt
|
||||||
|
|
||||||
sentry-sdk[fastapi]==2.19.0 # https://pypi.org/project/sentry-sdk/
|
sentry-sdk[fastapi]==2.25.1 # https://pypi.org/project/sentry-sdk/
|
||||||
|
@ -24,7 +24,7 @@ class ProjectSettings(ProjectBaseSettings):
|
|||||||
|
|
||||||
# Background task config
|
# Background task config
|
||||||
redis_url: RedisDsn = Field(RedisDsn(url="redis://redis:6379"))
|
redis_url: RedisDsn = Field(RedisDsn(url="redis://redis:6379"))
|
||||||
database_url: str = Field("psql://{{ cookiecutter.project_slug }}:{{ cookiecutter.project_slug }}@postgres:5432/{{ cookiecutter.project_slug }}")
|
database_url: str = Field("asyncpg://{{ cookiecutter.project_slug }}:{{ cookiecutter.project_slug }}@postgres:5432/{{ cookiecutter.project_slug }}")
|
||||||
|
|
||||||
# Various
|
# Various
|
||||||
timezone: str = Field(
|
timezone: str = Field(
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
|
from service.api.dependencies import QueryParams
|
||||||
from service.core.security import verify_password
|
from service.core.security import verify_password
|
||||||
|
from service.crud.user.models import UserPublic, UserRegister
|
||||||
|
from service.crud.utils import order_queryset
|
||||||
from service.database.models import User
|
from service.database.models import User
|
||||||
from ..utils import order_queryset
|
|
||||||
|
|
||||||
from ...api.dependencies import QueryParams
|
|
||||||
from .models import UserPublic, UserRegister
|
|
||||||
|
|
||||||
|
|
||||||
async def authenticate(*, username: str, password: str) -> User | None:
|
async def authenticate(*, username: str, password: str) -> User | None:
|
||||||
|
@ -4,5 +4,7 @@ from service.constants.types import PaginationParams
|
|||||||
|
|
||||||
|
|
||||||
def order_queryset(qs: QuerySet, filters: PaginationParams, default: str) -> QuerySet:
|
def order_queryset(qs: QuerySet, filters: PaginationParams, default: str) -> QuerySet:
|
||||||
|
ordering = None
|
||||||
|
if filters.order:
|
||||||
ordering = [f for f in filters.order.split(",") if f.split("-")[-1] in qs.fields]
|
ordering = [f for f in filters.order.split(",") if f.split("-")[-1] in qs.fields]
|
||||||
return qs.order_by(*(ordering or (default, )))
|
return qs.order_by(*(ordering or (default, )))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user