Form widgets & file uploads¶
Widget types¶
FastAdmin renders form fields with antd
components. Every widget type is available via the WidgetType enum:
| Widget | Renders as |
|---|---|
Input |
Single-line text input |
InputNumber |
Numeric input |
SlugInput |
Slug input (auto-slugified) |
EmailInput |
Email input |
PhoneInput |
Phone input with country codes |
UrlInput |
URL input |
PasswordInput |
Password input (on create, the value is stored via change_password) |
TextArea |
Multi-line text |
RichTextArea |
Rich-text (WYSIWYG) editor |
JsonTextArea |
JSON editor |
Select |
Select box |
AsyncSelect |
Select with async search (default for FK/M2M) |
AsyncTransfer |
Transfer (two-box) widget with async search |
Switch |
On/off switch |
Checkbox |
Checkbox |
TimePicker |
Time picker (ADMIN_TIME_FORMAT) |
DatePicker |
Date picker (ADMIN_DATE_FORMAT) |
DateTimePicker |
Datetime picker (ADMIN_DATETIME_FORMAT) |
RangePicker |
Date range picker |
RadioGroup |
Radio buttons |
CheckboxGroup |
Checkbox group |
UploadFile |
File upload |
UploadImage |
Image upload (with crop; disable via disableCropImage prop) |
formfield_overrides¶
Use formfield_overrides to pick a widget and props per field. label sets a
custom field label and help shows description text below the field; other
props are passed to the antd component:
from fastadmin import TortoiseModelAdmin, WidgetType, register
@register(User)
class UserAdmin(TortoiseModelAdmin):
formfield_overrides = {
"username": (
WidgetType.SlugInput,
{
"required": True,
"label": "Custom label",
"help": "Detailed description of the field",
},
),
"password": (WidgetType.PasswordInput, {"passwordModalForm": True}),
"bio": (WidgetType.RichTextArea, {}),
"avatar_url": (WidgetType.UploadImage, {"disableCropImage": True}),
}
File uploads¶
For file and image fields use the UploadFile / UploadImage widgets in
formfield_overrides and implement upload_file on the model admin. It
receives the raw file and must return the URL (or key) to store in the field —
e.g. after saving to disk or S3:
class UserAdmin(TortoiseModelAdmin):
formfield_overrides = {
"attachment": (WidgetType.UploadFile, {"required": False}),
}
async def upload_file(
self,
field_name: str,
file_name: str,
file_content: bytes,
obj=None, # None on the add page; the existing instance on the change page
) -> str:
path = Path("uploads") / file_name
path.write_bytes(file_content)
return f"/uploads/{file_name}"
Custom display URLs (get_file_url)¶
To customize the URL shown in the upload widget — e.g. generate an S3
presigned URL instead of displaying the raw s3:// key — override
get_file_url. The display URL is emitted as {field_name}__url in the
serialized object and passed to the widget as valueRepr; the raw stored
value is never changed, so form saves are unaffected:
async def get_file_url(self, field_name: str, value: str, obj=None) -> str:
# value is the raw stored key, e.g. "s3://bucket/key"
bucket, key = value.replace("s3://", "").split("/", 1)
async with aiobotocore.session.get_session().create_client("s3") as s3:
return await s3.generate_presigned_url(
"get_object",
Params={"Bucket": bucket, "Key": key},
ExpiresIn=3600,
)