mirror of
https://github.com/fastapi-admin/fastapi-admin.git
synced 2025-08-14 18:58:13 +08:00
Remove can_create
and add get_toolbar_actions
.
This commit is contained in:
@ -5,6 +5,7 @@
|
|||||||
### 1.0.1
|
### 1.0.1
|
||||||
|
|
||||||
- Add `column_attributes`.
|
- Add `column_attributes`.
|
||||||
|
- Remove `can_create` and add `get_toolbar_actions`.
|
||||||
|
|
||||||
### 1.0.0
|
### 1.0.0
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ from examples.models import Admin, Category, Config, Product
|
|||||||
from fastapi_admin.app import app
|
from fastapi_admin.app import app
|
||||||
from fastapi_admin.enums import Method
|
from fastapi_admin.enums import Method
|
||||||
from fastapi_admin.file_upload import FileUpload
|
from fastapi_admin.file_upload import FileUpload
|
||||||
from fastapi_admin.resources import Action, Dropdown, Field, Link, Model
|
from fastapi_admin.resources import Action, Dropdown, Field, Link, Model, ToolbarAction
|
||||||
from fastapi_admin.widgets import displays, filters, inputs
|
from fastapi_admin.widgets import displays, filters, inputs
|
||||||
|
|
||||||
upload = FileUpload(uploads_dir=os.path.join(BASE_DIR, "static", "uploads"))
|
upload = FileUpload(uploads_dir=os.path.join(BASE_DIR, "static", "uploads"))
|
||||||
@ -56,7 +56,8 @@ class AdminResource(Model):
|
|||||||
),
|
),
|
||||||
"created_at",
|
"created_at",
|
||||||
]
|
]
|
||||||
can_create = False
|
async def get_toolbar_actions(self, request: Request) -> List[ToolbarAction]:
|
||||||
|
return []
|
||||||
|
|
||||||
async def cell_attributes(self, request: Request, 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":
|
||||||
@ -92,7 +93,7 @@ class Content(Dropdown):
|
|||||||
"is_reviewed",
|
"is_reviewed",
|
||||||
"type",
|
"type",
|
||||||
Field(name="image", label="Image", display=displays.Image(width="40")),
|
Field(name="image", label="Image", display=displays.Image(width="40")),
|
||||||
Field(name="body", label='Body', input_=inputs.Editor()),
|
Field(name="body", label="Body", input_=inputs.Editor()),
|
||||||
"created_at",
|
"created_at",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ async def get_model_resource(request: Request, model=Depends(get_model)):
|
|||||||
raise HTTPException(status_code=HTTP_404_NOT_FOUND)
|
raise HTTPException(status_code=HTTP_404_NOT_FOUND)
|
||||||
actions = await model_resource.get_actions(request)
|
actions = await model_resource.get_actions(request)
|
||||||
bulk_actions = await model_resource.get_bulk_actions(request)
|
bulk_actions = await model_resource.get_bulk_actions(request)
|
||||||
|
toolbar_actions = await model_resource.get_toolbar_actions(request)
|
||||||
|
setattr(model_resource, "toolbar_actions", toolbar_actions)
|
||||||
setattr(model_resource, "actions", actions)
|
setattr(model_resource, "actions", actions)
|
||||||
setattr(model_resource, "bulk_actions", bulk_actions)
|
setattr(model_resource, "bulk_actions", bulk_actions)
|
||||||
return model_resource
|
return model_resource
|
||||||
|
@ -68,6 +68,10 @@ class Action(BaseModel):
|
|||||||
raise ValueError("ajax is False only available when method is Method.GET")
|
raise ValueError("ajax is False only available when method is Method.GET")
|
||||||
|
|
||||||
|
|
||||||
|
class ToolbarAction(Action):
|
||||||
|
class_: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
class Model(Resource):
|
class Model(Resource):
|
||||||
model: Type[TortoiseModel]
|
model: Type[TortoiseModel]
|
||||||
fields: List[Union[str, Field]] = []
|
fields: List[Union[str, Field]] = []
|
||||||
@ -78,6 +82,18 @@ class Model(Resource):
|
|||||||
can_create: bool = True
|
can_create: bool = True
|
||||||
enctype = "application/x-www-form-urlencoded"
|
enctype = "application/x-www-form-urlencoded"
|
||||||
|
|
||||||
|
async def get_toolbar_actions(self, request: Request) -> List[ToolbarAction]:
|
||||||
|
return [
|
||||||
|
ToolbarAction(
|
||||||
|
label=_("create"),
|
||||||
|
icon="fas fa-plus",
|
||||||
|
name="create",
|
||||||
|
method=Method.GET,
|
||||||
|
ajax=False,
|
||||||
|
class_="btn-dark",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
async def row_attributes(self, request: Request, obj: dict) -> dict:
|
async def row_attributes(self, request: Request, obj: dict) -> dict:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
@ -29,14 +29,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div class="ms-2">
|
<div class="ms-2">
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-search"
|
<i class="fas fa-search me-2"></i>
|
||||||
width="24" height="24" viewBox="0 0 24 24" stroke-width="2"
|
|
||||||
stroke="currentColor" fill="none" stroke-linecap="round"
|
|
||||||
stroke-linejoin="round">
|
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
|
||||||
<circle cx="10" cy="10" r="7"></circle>
|
|
||||||
<line x1="21" y1="21" x2="15" y2="15"></line>
|
|
||||||
</svg>
|
|
||||||
{{ _('search') }}
|
{{ _('search') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -72,18 +65,15 @@
|
|||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if model_resource.can_create %}
|
<div id="toolbar-actions" class="ms-auto btn-list">
|
||||||
<a class="ms-auto btn btn-dark" href="{{ request.app.admin_path }}/{{ resource }}/create">
|
{% for action in model_resource.toolbar_actions %}
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24"
|
<a class="btn {{ action.class_ }}"
|
||||||
stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
|
href="{{ request.app.admin_path }}/{{ resource }}/{{ action.name }}">
|
||||||
stroke-linejoin="round">
|
<i class="{{ action.icon }} me-2"></i>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
{{ action.label }}
|
||||||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
</a>
|
||||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
{% endfor %}
|
||||||
</svg>
|
</div>
|
||||||
{{ _('create') }}
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table card-table table-vcenter text-nowrap datatable">
|
<table class="table card-table table-vcenter text-nowrap datatable">
|
||||||
@ -121,11 +111,11 @@
|
|||||||
{% with outer_index = loop.index0 %}
|
{% with outer_index = loop.index0 %}
|
||||||
{% for x in value %}
|
{% for x in value %}
|
||||||
<td {% for k,v in cell_attributes[outer_index][loop.index0].items() %}
|
<td {% for k,v in cell_attributes[outer_index][loop.index0].items() %}
|
||||||
{{ k }}="{{ v }}"{% endfor %}>{{ x|safe }}</td>
|
{{ k }}="{{ v }}"{% endfor %}>{{ x|safe }}</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% if model_resource.actions %}
|
{% if model_resource.actions %}
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<span class="dropdown">
|
<span class="dropdown">
|
||||||
<button
|
<button
|
||||||
class="btn dropdown-toggle align-text-top"
|
class="btn dropdown-toggle align-text-top"
|
||||||
@ -154,8 +144,8 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -15,7 +15,7 @@ class Input(Widget):
|
|||||||
template = "widgets/inputs/input.html"
|
template = "widgets/inputs/input.html"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, help_text: Optional[str] = None, default: Any = None, null: bool = False, **context
|
self, help_text: Optional[str] = None, default: Any = None, null: bool = False, **context
|
||||||
):
|
):
|
||||||
super().__init__(null=null, help_text=help_text, **context)
|
super().__init__(null=null, help_text=help_text, **context)
|
||||||
self.default = default
|
self.default = default
|
||||||
@ -44,12 +44,12 @@ class Text(Input):
|
|||||||
input_type: Optional[str] = "text"
|
input_type: Optional[str] = "text"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
help_text: Optional[str] = None,
|
help_text: Optional[str] = None,
|
||||||
default: Any = None,
|
default: Any = None,
|
||||||
null: bool = False,
|
null: bool = False,
|
||||||
placeholder: str = "",
|
placeholder: str = "",
|
||||||
disabled: bool = False,
|
disabled: bool = False,
|
||||||
):
|
):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
null=null,
|
null=null,
|
||||||
@ -65,11 +65,11 @@ class Select(Input):
|
|||||||
template = "widgets/inputs/select.html"
|
template = "widgets/inputs/select.html"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
help_text: Optional[str] = None,
|
help_text: Optional[str] = None,
|
||||||
default: Any = None,
|
default: Any = None,
|
||||||
null: bool = False,
|
null: bool = False,
|
||||||
disabled: bool = False,
|
disabled: bool = False,
|
||||||
):
|
):
|
||||||
super().__init__(help_text=help_text, null=null, default=default, disabled=disabled)
|
super().__init__(help_text=help_text, null=null, default=default, disabled=disabled)
|
||||||
|
|
||||||
@ -91,12 +91,12 @@ class Select(Input):
|
|||||||
|
|
||||||
class ForeignKey(Select):
|
class ForeignKey(Select):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
model: Type[Model],
|
model: Type[Model],
|
||||||
default: Any = None,
|
default: Any = None,
|
||||||
null: bool = False,
|
null: bool = False,
|
||||||
disabled: bool = False,
|
disabled: bool = False,
|
||||||
help_text: Optional[str] = None,
|
help_text: Optional[str] = None,
|
||||||
):
|
):
|
||||||
super().__init__(help_text=help_text, default=default, null=null, disabled=disabled)
|
super().__init__(help_text=help_text, default=default, null=null, disabled=disabled)
|
||||||
self.model = model
|
self.model = model
|
||||||
@ -116,10 +116,10 @@ class ManyToMany(Select):
|
|||||||
template = "widgets/inputs/many_to_many.html"
|
template = "widgets/inputs/many_to_many.html"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
model: Type[Model],
|
model: Type[Model],
|
||||||
disabled: bool = False,
|
disabled: bool = False,
|
||||||
help_text: Optional[str] = None,
|
help_text: Optional[str] = None,
|
||||||
):
|
):
|
||||||
super().__init__(help_text=help_text, disabled=disabled)
|
super().__init__(help_text=help_text, disabled=disabled)
|
||||||
self.model = model
|
self.model = model
|
||||||
@ -144,13 +144,13 @@ class ManyToMany(Select):
|
|||||||
|
|
||||||
class Enum(Select):
|
class Enum(Select):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
enum: Type[EnumCLS],
|
enum: Type[EnumCLS],
|
||||||
default: Any = None,
|
default: Any = None,
|
||||||
enum_type: Type = int,
|
enum_type: Type = int,
|
||||||
null: bool = False,
|
null: bool = False,
|
||||||
disabled: bool = False,
|
disabled: bool = False,
|
||||||
help_text: Optional[str] = None,
|
help_text: Optional[str] = None,
|
||||||
):
|
):
|
||||||
super().__init__(help_text=help_text, default=default, null=null, disabled=disabled)
|
super().__init__(help_text=help_text, default=default, null=null, disabled=disabled)
|
||||||
self.enum = enum
|
self.enum = enum
|
||||||
@ -174,10 +174,10 @@ class Json(Input):
|
|||||||
template = "widgets/inputs/json.html"
|
template = "widgets/inputs/json.html"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
help_text: Optional[str] = None,
|
help_text: Optional[str] = None,
|
||||||
null: bool = False,
|
null: bool = False,
|
||||||
options: Optional[dict] = None,
|
options: Optional[dict] = None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
options config to jsoneditor, see https://github.com/josdejong/jsoneditor
|
options config to jsoneditor, see https://github.com/josdejong/jsoneditor
|
||||||
@ -215,12 +215,12 @@ class File(Input):
|
|||||||
input_type = "file"
|
input_type = "file"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
upload: FileUpload,
|
upload: FileUpload,
|
||||||
default: Any = None,
|
default: Any = None,
|
||||||
null: bool = False,
|
null: bool = False,
|
||||||
disabled: bool = False,
|
disabled: bool = False,
|
||||||
help_text: Optional[str] = None,
|
help_text: Optional[str] = None,
|
||||||
):
|
):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
null=null,
|
null=null,
|
||||||
@ -246,11 +246,11 @@ class Radio(Select):
|
|||||||
template = "widgets/inputs/radio.html"
|
template = "widgets/inputs/radio.html"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
options: List[Tuple[str, Any]],
|
options: List[Tuple[str, Any]],
|
||||||
help_text: Optional[str] = None,
|
help_text: Optional[str] = None,
|
||||||
default: Any = None,
|
default: Any = None,
|
||||||
disabled: bool = False,
|
disabled: bool = False,
|
||||||
):
|
):
|
||||||
super().__init__(default=default, disabled=disabled, help_text=help_text)
|
super().__init__(default=default, disabled=disabled, help_text=help_text)
|
||||||
self.options = options
|
self.options = options
|
||||||
|
Reference in New Issue
Block a user