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