mirror of
https://github.com/fastapi-admin/fastapi-admin.git
synced 2025-08-14 18:58:13 +08:00
add request params
This commit is contained in:
@ -38,8 +38,7 @@ async def startup():
|
|||||||
logo_url="https://preview.tabler.io/static/logo-white.svg",
|
logo_url="https://preview.tabler.io/static/logo-white.svg",
|
||||||
login_logo_url="https://preview.tabler.io/static/logo.svg",
|
login_logo_url="https://preview.tabler.io/static/logo.svg",
|
||||||
template_folders=[os.path.join(BASE_DIR, "templates")],
|
template_folders=[os.path.join(BASE_DIR, "templates")],
|
||||||
login_provider=login_provider,
|
providers=[login_provider],
|
||||||
maintenance=False,
|
|
||||||
redis=redis,
|
redis=redis,
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
@ -119,10 +118,10 @@ class AdminResource(Model):
|
|||||||
]
|
]
|
||||||
can_create = False
|
can_create = False
|
||||||
|
|
||||||
def get_actions(self) -> List[Action]:
|
async def get_actions(self,request:Request) -> List[Action]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_bulk_actions(self) -> List[Action]:
|
async def get_bulk_actions(self,request:Request) -> List[Action]:
|
||||||
return []
|
return []
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from starlette.requests import Request
|
||||||
|
|
||||||
from examples import enums
|
from examples import enums
|
||||||
from examples.constants import BASE_DIR
|
from examples.constants import BASE_DIR
|
||||||
from examples.models import Admin, Category, Config, Product
|
from examples.models import Admin, Category, Config, Product
|
||||||
@ -55,10 +57,10 @@ class AdminResource(Model):
|
|||||||
]
|
]
|
||||||
can_create = False
|
can_create = False
|
||||||
|
|
||||||
def cell_attributes(self, obj: dict, field: Field) -> dict:
|
async def cell_attributes(self, request: Request, obj: dict, field: Field) -> dict:
|
||||||
if field.name == "id":
|
if field.name == "id":
|
||||||
return {"class": "bg-danger"}
|
return {"class": "bg-danger text-white"}
|
||||||
return super().cell_attributes(obj, field)
|
return await super().cell_attributes(request, obj, field)
|
||||||
|
|
||||||
def get_actions(self) -> List[Action]:
|
def get_actions(self) -> List[Action]:
|
||||||
return []
|
return []
|
||||||
@ -119,10 +121,10 @@ class ConfigResource(Model):
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
def row_attributes(self, obj: dict) -> dict:
|
async def row_attributes(self, request: Request, obj: dict) -> dict:
|
||||||
if obj.get("status") == enums.Status.on:
|
if obj.get("status") == enums.Status.on:
|
||||||
return {"class": "bg-green text-white"}
|
return {"class": "bg-green text-white"}
|
||||||
return super().row_attributes(obj)
|
return await super().row_attributes(obj)
|
||||||
|
|
||||||
|
|
||||||
@app.register
|
@app.register
|
||||||
|
@ -2,6 +2,7 @@ from typing import List, Optional, Type, Union
|
|||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from starlette.datastructures import FormData
|
from starlette.datastructures import FormData
|
||||||
|
from starlette.requests import Request
|
||||||
from tortoise import ForeignKeyFieldInstance, ManyToManyFieldInstance
|
from tortoise import ForeignKeyFieldInstance, ManyToManyFieldInstance
|
||||||
from tortoise import Model as TortoiseModel
|
from tortoise import Model as TortoiseModel
|
||||||
from tortoise.fields import BooleanField, DateField, DatetimeField, JSONField
|
from tortoise.fields import BooleanField, DateField, DatetimeField, JSONField
|
||||||
@ -70,10 +71,10 @@ class Model(Resource):
|
|||||||
can_create: bool = True
|
can_create: bool = True
|
||||||
enctype = "application/x-www-form-urlencoded"
|
enctype = "application/x-www-form-urlencoded"
|
||||||
|
|
||||||
def row_attributes(self, obj: dict) -> dict:
|
async def row_attributes(self, request: Request, obj: dict) -> dict:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def cell_attributes(self, obj: dict, field: Field) -> dict:
|
async def cell_attributes(self, request: Request, obj: dict, field: Field) -> dict:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def get_actions(self) -> List[Action]:
|
def get_actions(self) -> List[Action]:
|
||||||
@ -135,14 +136,14 @@ class Model(Resource):
|
|||||||
return ret, m2m_ret
|
return ret, m2m_ret
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_filters(cls, values: Optional[dict] = None):
|
async def get_filters(cls, request: Request, values: Optional[dict] = None):
|
||||||
if not values:
|
if not values:
|
||||||
values = {}
|
values = {}
|
||||||
ret = []
|
ret = []
|
||||||
for f in cls.filters:
|
for f in cls.filters:
|
||||||
name = f.context.get("name")
|
name = f.context.get("name")
|
||||||
value = values.get(name)
|
value = values.get(name)
|
||||||
ret.append(await f.render(value))
|
ret.append(await f.render(request, value))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -29,7 +29,7 @@ async def list_view(
|
|||||||
fields_label = model_resource.get_fields_label()
|
fields_label = model_resource.get_fields_label()
|
||||||
fields = model_resource.get_fields()
|
fields = model_resource.get_fields()
|
||||||
params = await model_resource.resolve_query_params(dict(request.query_params))
|
params = await model_resource.resolve_query_params(dict(request.query_params))
|
||||||
filters = await model_resource.get_filters(params)
|
filters = await model_resource.get_filters(request, params)
|
||||||
qs = model.filter(**params)
|
qs = model.filter(**params)
|
||||||
total = await qs.count()
|
total = await qs.count()
|
||||||
if page_size:
|
if page_size:
|
||||||
@ -38,13 +38,17 @@ async def list_view(
|
|||||||
page_size = model_resource.page_size
|
page_size = model_resource.page_size
|
||||||
qs = qs.offset((page_num - 1) * page_size)
|
qs = qs.offset((page_num - 1) * page_size)
|
||||||
values = await qs.values(*fields_name)
|
values = await qs.values(*fields_name)
|
||||||
rendered_values = await render_values(fields, values)
|
rendered_values, row_attributes, cell_attributes = await render_values(
|
||||||
|
request, model_resource, fields, values
|
||||||
|
)
|
||||||
context = {
|
context = {
|
||||||
"request": request,
|
"request": request,
|
||||||
"resources": resources,
|
"resources": resources,
|
||||||
"fields_label": fields_label,
|
"fields_label": fields_label,
|
||||||
"fields": fields,
|
"fields": fields,
|
||||||
"values": values,
|
"values": values,
|
||||||
|
"row_attributes": row_attributes,
|
||||||
|
"cell_attributes": cell_attributes,
|
||||||
"rendered_values": rendered_values,
|
"rendered_values": rendered_values,
|
||||||
"filters": filters,
|
"filters": filters,
|
||||||
"resource": resource,
|
"resource": resource,
|
||||||
|
@ -12,7 +12,7 @@ from fastapi_admin import VERSION
|
|||||||
from fastapi_admin.constants import BASE_DIR
|
from fastapi_admin.constants import BASE_DIR
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from fastapi_admin.resources import Field
|
from fastapi_admin.resources import Field, Model
|
||||||
|
|
||||||
templates = Jinja2Templates(directory=os.path.join(BASE_DIR, "templates"))
|
templates = Jinja2Templates(directory=os.path.join(BASE_DIR, "templates"))
|
||||||
templates.env.globals["VERSION"] = VERSION
|
templates.env.globals["VERSION"] = VERSION
|
||||||
@ -46,22 +46,34 @@ def add_template_folder(*folders: str):
|
|||||||
|
|
||||||
|
|
||||||
async def render_values(
|
async def render_values(
|
||||||
fields: List["Field"], values: List[Tuple[Any]], display: bool = True
|
request: Request,
|
||||||
) -> List[List[Any]]:
|
model: "Model",
|
||||||
|
fields: List["Field"],
|
||||||
|
values: List[typing.Dict[str, Any]],
|
||||||
|
display: bool = True,
|
||||||
|
) -> typing.Tuple[List[List[Any]], List[dict], List[List[dict]]]:
|
||||||
"""
|
"""
|
||||||
render values with template render
|
render values with template render
|
||||||
:param fields:
|
:param fields:
|
||||||
:param values:
|
:param values:
|
||||||
:param display:
|
:param display:
|
||||||
|
:params request:
|
||||||
|
:params model:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
|
cell_attributes: List[List[dict]] = []
|
||||||
|
row_attributes: List[dict] = []
|
||||||
for value in values:
|
for value in values:
|
||||||
|
row_attributes.append(await model.row_attributes(request, value))
|
||||||
item = []
|
item = []
|
||||||
|
cell_item = []
|
||||||
for i, k in enumerate(value):
|
for i, k in enumerate(value):
|
||||||
|
cell_item.append(await model.cell_attributes(request, value, fields[i]))
|
||||||
if display:
|
if display:
|
||||||
item.append(await fields[i].display.render(value[k]))
|
item.append(await fields[i].display.render(request, value[k]))
|
||||||
else:
|
else:
|
||||||
item.append(await fields[i].input.render(value[k]))
|
item.append(await fields[i].input.render(request, value[k]))
|
||||||
ret.append(item)
|
ret.append(item)
|
||||||
return ret
|
cell_attributes.append(cell_item)
|
||||||
|
return ret, row_attributes, cell_attributes
|
||||||
|
@ -108,7 +108,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for value in rendered_values %}
|
{% for value in rendered_values %}
|
||||||
<tr {% for k,v in model_resource.row_attributes(values[loop.index0]).items() %}{{ k }}="{{ v }}"{% endfor %}>
|
<tr {% for k,v in row_attributes[loop.index0].items() %}{{ k }}="{{ v }}"{% endfor %}>
|
||||||
{% if model_resource.bulk_actions %}
|
{% if model_resource.bulk_actions %}
|
||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
@ -120,8 +120,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% with outer_index = loop.index0 %}
|
{% with outer_index = loop.index0 %}
|
||||||
{% for x in value %}
|
{% for x in value %}
|
||||||
<td
|
<td {% for k,v in cell_attributes[outer_index][loop.index0].items() %}
|
||||||
{% for k,v in model_resource.cell_attributes(values[outer_index],fields[loop.index0]).items() %}
|
|
||||||
{{ k }}="{{ v }}"{% endfor %}>{{ x|safe }}</td>
|
{{ k }}="{{ v }}"{% endfor %}>{{ x|safe }}</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
26
poetry.lock
generated
26
poetry.lock
generated
@ -84,17 +84,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "attrs"
|
name = "attrs"
|
||||||
version = "20.3.0"
|
version = "21.1.0"
|
||||||
description = "Classes Without Boilerplate"
|
description = "Classes Without Boilerplate"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "furo", "sphinx", "pre-commit"]
|
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"]
|
||||||
docs = ["furo", "sphinx", "zope.interface"]
|
docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
|
||||||
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
|
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
|
||||||
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"]
|
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "babel"
|
name = "babel"
|
||||||
@ -643,7 +643,7 @@ python-versions = ">=3.7,<4.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "6.2.3"
|
version = "6.2.4"
|
||||||
description = "pytest: simple powerful testing with Python"
|
description = "pytest: simple powerful testing with Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@ -768,7 +768,7 @@ python-versions = "*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "six"
|
name = "six"
|
||||||
version = "1.15.0"
|
version = "1.16.0"
|
||||||
description = "Python 2 and 3 compatibility utilities"
|
description = "Python 2 and 3 compatibility utilities"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@ -974,8 +974,8 @@ atomicwrites = [
|
|||||||
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
|
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
|
||||||
]
|
]
|
||||||
attrs = [
|
attrs = [
|
||||||
{file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"},
|
{file = "attrs-21.1.0-py2.py3-none-any.whl", hash = "sha256:8ee1e5f5a1afc5b19bdfae4fdf0c35ed324074bdce3500c939842c8f818645d9"},
|
||||||
{file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"},
|
{file = "attrs-21.1.0.tar.gz", hash = "sha256:3901be1cb7c2a780f14668691474d9252c070a756be0a9ead98cfeabfa11aeb8"},
|
||||||
]
|
]
|
||||||
babel = [
|
babel = [
|
||||||
{file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"},
|
{file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"},
|
||||||
@ -1365,8 +1365,8 @@ pypika-tortoise = [
|
|||||||
{file = "pypika_tortoise-0.1.0-py3-none-any.whl", hash = "sha256:ec83b0b2964be01ef563f5f019b0332a18177604e841c47ad39d798798c6dfe9"},
|
{file = "pypika_tortoise-0.1.0-py3-none-any.whl", hash = "sha256:ec83b0b2964be01ef563f5f019b0332a18177604e841c47ad39d798798c6dfe9"},
|
||||||
]
|
]
|
||||||
pytest = [
|
pytest = [
|
||||||
{file = "pytest-6.2.3-py3-none-any.whl", hash = "sha256:6ad9c7bdf517a808242b998ac20063c41532a570d088d77eec1ee12b0b5574bc"},
|
{file = "pytest-6.2.4-py3-none-any.whl", hash = "sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"},
|
||||||
{file = "pytest-6.2.3.tar.gz", hash = "sha256:671238a46e4df0f3498d1c3270e5deb9b32d25134c99b7d75370a68cfbe9b634"},
|
{file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"},
|
||||||
]
|
]
|
||||||
pytest-asyncio = [
|
pytest-asyncio = [
|
||||||
{file = "pytest-asyncio-0.15.1.tar.gz", hash = "sha256:2564ceb9612bbd560d19ca4b41347b54e7835c2f792c504f698e05395ed63f6f"},
|
{file = "pytest-asyncio-0.15.1.tar.gz", hash = "sha256:2564ceb9612bbd560d19ca4b41347b54e7835c2f792c504f698e05395ed63f6f"},
|
||||||
@ -1470,8 +1470,8 @@ regex = [
|
|||||||
{file = "regex-2021.4.4.tar.gz", hash = "sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb"},
|
{file = "regex-2021.4.4.tar.gz", hash = "sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb"},
|
||||||
]
|
]
|
||||||
six = [
|
six = [
|
||||||
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
|
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||||
{file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
|
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||||
]
|
]
|
||||||
smmap = [
|
smmap = [
|
||||||
{file = "smmap-4.0.0-py2.py3-none-any.whl", hash = "sha256:a9a7479e4c572e2e775c404dcd3080c8dc49f39918c2cf74913d30c4c478e3c2"},
|
{file = "smmap-4.0.0-py2.py3-none-any.whl", hash = "sha256:a9a7479e4c572e2e775c404dcd3080c8dc49f39918c2cf74913d30c4c478e3c2"},
|
||||||
|
Reference in New Issue
Block a user