mirror of
https://github.com/fastapi-admin/fastapi-admin.git
synced 2026-03-13 10:32:25 +08:00
Add column_attributes
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## 1.0
|
||||
|
||||
### 1.0.1
|
||||
|
||||
- Add `column_attributes`.
|
||||
|
||||
### 1.0.0
|
||||
|
||||
**This is a completely different version and rewrite all code. If you are using old version, you can't upgrade directly,
|
||||
|
||||
@@ -52,11 +52,11 @@ async def startup():
|
||||
Admin,
|
||||
settings.GOOGLE_CLIENT_ID,
|
||||
settings.GOOGLE_CLIENT_SECRET,
|
||||
redirect_uri="https://fastapi-admin-pro.long2ice.cn/admin/login/google_oauth2_provider",
|
||||
redirect_uri="https://fastapi-admin-pro.long2ice.cn/admin/oauth2/google_oauth2_provider",
|
||||
),
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
If you want custom oauth2 provider, just inherit `fastapi_admin.providers.login.OAuth2Provider` and implement its
|
||||
methods.
|
||||
methods. And the `redirect_uri` format is `{server_url}/{admin_path}/oauth2/{provider_name}`.
|
||||
|
||||
@@ -50,7 +50,8 @@ class AdminResource(Model):
|
||||
]
|
||||
```
|
||||
|
||||
You can pass `str` or `Field` to `fields`, if is `str`, it will try to auto mapping display and input widget, such as `displays.Boolean` for `BooleanField`, `inputs.Date` for `DateField`.
|
||||
You can pass `str` or `Field` to `fields`, if is `str`, it will try to auto mapping display and input widget, such
|
||||
as `displays.Boolean` for `BooleanField`, `inputs.Date` for `DateField`.
|
||||
|
||||
All kind of widgets you can find in [Display](/reference/widget/display/) and [Input](/reference/widget/input/).
|
||||
|
||||
@@ -58,9 +59,11 @@ All kind of widgets you can find in [Display](/reference/widget/display/) and [I
|
||||
|
||||
The `Action` define the action display in every end of row, and bulk action for every model.
|
||||
|
||||
By default there are two actions, Which are delete action and edit action, and one bulk action, which allow delete rows in bulk.
|
||||
By default there are two actions, Which are delete action and edit action, and one bulk action, which allow delete rows
|
||||
in bulk.
|
||||
|
||||
To use that, you should override the `get_actions` and `get_bulk_actions`. The following example hide all default actions with return empty list.
|
||||
To use that, you should override the `get_actions` and `get_bulk_actions`. The following example hide all default
|
||||
actions with return empty list.
|
||||
|
||||
```python
|
||||
@app.register
|
||||
@@ -74,7 +77,8 @@ class AdminResource(Model):
|
||||
|
||||
## Model
|
||||
|
||||
`Model` is the core resource, which make TortoiseORM model as a menu and display a data table with create, update, and delete.
|
||||
`Model` is the core resource, which make TortoiseORM model as a menu and display a data table with create, update, and
|
||||
delete.
|
||||
|
||||
```python
|
||||
@app.register
|
||||
@@ -101,8 +105,9 @@ class AdminResource(Model):
|
||||
- `model`: TortoiseORM model.
|
||||
- `page_pre_title`: Show page pre title in content.
|
||||
- `page_title`: Show page title in content.
|
||||
- `filters`: Define filters for the model, which will display filter inputs in table above, all kinds of filters you can find in [Filter](/reference/widget/filter/).
|
||||
- `can_delete`: Whether show a `create` button there.
|
||||
- `filters`: Define filters for the model, which will display filter inputs in table above, all kinds of filters you can
|
||||
find in [Filter](/reference/widget/filter/).
|
||||
- `can_create`: Whether show a `create` button there.
|
||||
|
||||
### row_attributes
|
||||
|
||||
@@ -119,17 +124,33 @@ class ConfigResource(Model):
|
||||
|
||||
The example above will add the css `class = "bg-green text-white"` for the row which `status = enums.Status.on`.
|
||||
|
||||
### column_attributes
|
||||
|
||||
You can add extra attributes to each column by use `column_attributes`.
|
||||
|
||||
```python
|
||||
@app.register
|
||||
class LogResource(Model):
|
||||
async def column_attributes(self, request: Request, field: Field) -> dict:
|
||||
if field.name == "content":
|
||||
return {"class": "w-50"}
|
||||
return await super().column_attributes(request, field)
|
||||
```
|
||||
|
||||
The example above will add the css `class = "w-50"` for the column which `content`.
|
||||
|
||||
### cell_attributes
|
||||
|
||||
Same as `row_attributes` but for the cell, you can add extra attributes to cell depends on the row object and column field.
|
||||
Same as `row_attributes` but for the cell, you can add extra attributes to cell depends on the row object and column
|
||||
field.
|
||||
|
||||
```python
|
||||
@app.register
|
||||
class AdminResource(Model):
|
||||
async def cell_attributes(self, request: Request, obj: dict, field: Field) -> dict:
|
||||
if field.name == "id":
|
||||
return {"class": "bg-danger text-white"}
|
||||
return await super().cell_attributes(request, obj, field)
|
||||
if field.name == "id":
|
||||
return {"class": "bg-danger text-white"}
|
||||
return await super().cell_attributes(request, obj, field)
|
||||
```
|
||||
|
||||
## Dropdown
|
||||
|
||||
@@ -4,15 +4,9 @@ from aioredis import Redis
|
||||
from fastapi import FastAPI
|
||||
from pydantic import HttpUrl
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.status import HTTP_403_FORBIDDEN, HTTP_404_NOT_FOUND, HTTP_500_INTERNAL_SERVER_ERROR
|
||||
from tortoise import Model
|
||||
|
||||
from fastapi_admin import i18n
|
||||
from fastapi_admin.exceptions import (
|
||||
forbidden_error_exception,
|
||||
not_found_error_exception,
|
||||
server_error_exception,
|
||||
)
|
||||
|
||||
from . import middlewares, template
|
||||
from .providers import Provider
|
||||
|
||||
@@ -75,6 +75,9 @@ class Model(Resource):
|
||||
async def row_attributes(self, request: Request, obj: dict) -> dict:
|
||||
return {}
|
||||
|
||||
async def column_attributes(self, request: Request, field: Field) -> dict:
|
||||
return {}
|
||||
|
||||
async def cell_attributes(self, request: Request, obj: dict, field: Field) -> dict:
|
||||
return {}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
from .password import router as password_router
|
||||
from .resources import router as resources_router
|
||||
|
||||
router = APIRouter()
|
||||
router.include_router(resources_router)
|
||||
router.include_router(password_router, prefix="/password")
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
from fastapi import APIRouter, Depends, Form
|
||||
from starlette.requests import Request
|
||||
|
||||
from fastapi_admin.depends import get_current_admin, get_resources
|
||||
from fastapi_admin.i18n import _
|
||||
from fastapi_admin.models import AbstractAdmin
|
||||
from fastapi_admin.template import templates
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def update_password_view(
|
||||
request: Request,
|
||||
resources=Depends(get_resources),
|
||||
):
|
||||
return templates.TemplateResponse(
|
||||
"password.html",
|
||||
context={
|
||||
"request": request,
|
||||
"resources": resources,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def update_password(
|
||||
request: Request,
|
||||
old_password: str = Form(...),
|
||||
new_password: str = Form(...),
|
||||
re_new_password: str = Form(...),
|
||||
admin: AbstractAdmin = Depends(get_current_admin),
|
||||
resources=Depends(get_resources),
|
||||
):
|
||||
login_provider = request.app.login_provider
|
||||
error = None
|
||||
if not login_provider.check_password(admin, old_password):
|
||||
error = _("old_password_error")
|
||||
elif new_password != re_new_password:
|
||||
error = _("new_password_different")
|
||||
if error:
|
||||
return templates.TemplateResponse(
|
||||
"password.html",
|
||||
context={"request": request, "resources": resources, "error": error},
|
||||
)
|
||||
await login_provider.update_password(admin, new_password)
|
||||
return await login_provider.logout(request)
|
||||
@@ -38,7 +38,7 @@ 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, row_attributes, cell_attributes = await render_values(
|
||||
rendered_values, row_attributes, column_attributes, cell_attributes = await render_values(
|
||||
request, model_resource, fields, values
|
||||
)
|
||||
context = {
|
||||
@@ -48,6 +48,7 @@ async def list_view(
|
||||
"fields": fields,
|
||||
"values": values,
|
||||
"row_attributes": row_attributes,
|
||||
"column_attributes": column_attributes,
|
||||
"cell_attributes": cell_attributes,
|
||||
"rendered_values": rendered_values,
|
||||
"filters": filters,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import typing
|
||||
from datetime import date
|
||||
from typing import Any, List, Tuple
|
||||
from typing import Any, List
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from jinja2 import contextfilter
|
||||
@@ -51,7 +51,7 @@ async def render_values(
|
||||
fields: List["Field"],
|
||||
values: List[typing.Dict[str, Any]],
|
||||
display: bool = True,
|
||||
) -> typing.Tuple[List[List[Any]], List[dict], List[List[dict]]]:
|
||||
) -> typing.Tuple[List[List[Any]], List[dict], List[dict], List[List[dict]]]:
|
||||
"""
|
||||
render values with template render
|
||||
:param fields:
|
||||
@@ -64,6 +64,9 @@ async def render_values(
|
||||
ret = []
|
||||
cell_attributes: List[List[dict]] = []
|
||||
row_attributes: List[dict] = []
|
||||
column_attributes: List[dict] = []
|
||||
for field in fields:
|
||||
column_attributes.append(await model.column_attributes(request, field))
|
||||
for value in values:
|
||||
row_attributes.append(await model.row_attributes(request, value))
|
||||
item = []
|
||||
@@ -76,4 +79,4 @@ async def render_values(
|
||||
item.append(await fields[i].input.render(request, value[k]))
|
||||
ret.append(item)
|
||||
cell_attributes.append(cell_item)
|
||||
return ret, row_attributes, cell_attributes
|
||||
return ret, row_attributes, column_attributes, cell_attributes
|
||||
|
||||
@@ -18,7 +18,7 @@ packages = [
|
||||
]
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/fastapi-admin/fastapi-admin.git"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
Babel = "*"
|
||||
|
||||
Reference in New Issue
Block a user