Add custom filters

This commit is contained in:
long2ice
2020-10-19 17:55:17 +08:00
parent 0e95a7b146
commit 9b4a41b3f9
7 changed files with 86 additions and 4 deletions

View File

@@ -8,6 +8,7 @@ from tortoise import Model
from . import enums
from .common import get_all_models, import_obj, pwd_context
from .exceptions import exception_handler
from .filters import SearchFilter
from .models import AbstractAdminLog, AbstractPermission, AbstractRole, AbstractUser
from .schemas import LoginIn
from .shortcuts import get_object_or_404
@@ -244,6 +245,11 @@ class AdminApp(FastAPI):
sort_fields = menu.sort_fields
fields = {}
pk = name = pk_field.get("name")
# CustomSearchFilters
for search_filter in filter(
lambda x: type(x).__name__ == "type" and issubclass(x, SearchFilter), search_fields
):
search_fields_ret[search_filter.get_name()] = await search_filter.get_field()
if not exclude_pk and not self._exclude_field(resource, name):
field = Field(
label=pk_field.get("name").title(),

36
fastapi_admin/filters.py Normal file
View File

@@ -0,0 +1,36 @@
from typing import Any
from tortoise import QuerySet
from fastapi_admin.site import Field
_search_filters = {}
class Filter:
@classmethod
def get_queryset(cls, queryset: QuerySet) -> QuerySet:
raise NotImplementedError
class SearchFilter:
@classmethod
def get_queryset(cls, queryset: QuerySet, option: Any) -> QuerySet:
raise NotImplementedError
@classmethod
async def get_field(cls) -> Field:
raise NotImplementedError
@classmethod
def get_name(cls) -> str:
raise NotImplementedError
def register_filter(cls: SearchFilter):
_search_filters[cls.get_name()] = cls
return cls
def get_filter_by_name(name: str):
return _search_filters.get(name)

View File

@@ -27,6 +27,7 @@ from ..depends import (
update_checker,
)
from ..factory import app
from ..filters import get_filter_by_name
from ..responses import GetManyOut
from ..schemas import BulkIn
from ..shortcuts import get_object_or_404
@@ -83,8 +84,15 @@ async def get_resource(
):
menu = app.model_menu_mapping[resource]
qs = model.all()
for filter_ in menu.custom_filters:
qs = filter_.get_queryset(qs)
if query.where:
qs = qs.filter(**query.where)
for name, value in query.where.items():
filter_cls = get_filter_by_name(name)
if filter_cls:
qs = filter_cls.get_queryset(qs, value)
else:
qs = qs.filter(**{name: value})
sort = query.sort
for k, v in sort.items():
if k in menu.sort_fields:

View File

@@ -1,4 +1,4 @@
from typing import Dict, List, Optional, Tuple, Union
from typing import Dict, List, Optional, Tuple, Type, Union
from pydantic import BaseModel, HttpUrl
@@ -19,7 +19,7 @@ class Menu(BaseModel):
# raw id fields
raw_id_fields: Optional[Tuple[str, ...]] = tuple()
# searchable fields
search_fields: Optional[Tuple[str, ...]] = tuple()
search_fields = tuple()
# sortable fields
sort_fields: Optional[Tuple[str, ...]] = tuple()
# define field type,like select,radiolist,text,date
@@ -31,6 +31,7 @@ class Menu(BaseModel):
import_: bool = False
actions: Optional[Dict]
bulk_actions: List[Dict] = [{"value": "delete", "text": "delete_all"}]
custom_filters: List = []
Menu.update_forward_refs()