-
Notifications
You must be signed in to change notification settings - Fork 45
add enum support to custom forms #436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 6 commits
c3e2432
a0711c4
90e92b5
05dc4c8
e62465e
4a14402
b08950e
eb0f903
decc315
7c1198f
8703d24
3cb1f9a
549d1d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,12 +4,14 @@ | |
|
|
||
| from __future__ import annotations | ||
|
|
||
| import enum | ||
| import inspect | ||
| import io | ||
| import itertools | ||
| import json | ||
| import logging | ||
| import os | ||
| import sys | ||
| import typing as t | ||
| from dataclasses import dataclass | ||
| from datetime import timedelta | ||
|
|
@@ -62,8 +64,15 @@ | |
| TranslationListItem, | ||
| TranslationListResponse, | ||
| ) | ||
| from .utils import convert_enum_to_choices | ||
| from .version import __VERSION__ as PICCOLO_ADMIN_VERSION | ||
|
|
||
| if sys.version_info < (3, 11): | ||
| ENUMTYPE = enum.EnumMeta | ||
| else: | ||
| ENUMTYPE = enum.EnumType | ||
|
|
||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
|
|
@@ -403,6 +412,24 @@ def __init__( | |
| self.description = description | ||
| self.form_group = form_group | ||
| self.slug = self.name.replace(" ", "-").lower() | ||
| for ( | ||
| field_name, | ||
| field_value, | ||
| ) in self.pydantic_model.model_fields.items(): | ||
| if isinstance(field_value.annotation, ENUMTYPE): | ||
|
||
| # update model_fields, field annotation and | ||
| # rebuild the model for the changes to take effect | ||
| pydantic_model.model_fields[field_name] = Field( | ||
| json_schema_extra={ | ||
| "extra": { | ||
| "choices": convert_enum_to_choices( | ||
| field_value.annotation | ||
| ) | ||
| } | ||
| }, | ||
| ) | ||
| pydantic_model.model_fields[field_name].annotation = str | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we just leave the annotation as what it was originally?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to reassign the annotation type because if we don't, that annotation is
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yes - I forgot that the front end would get confused by the open api schema is we leave the enum in there. |
||
| pydantic_model.model_rebuild(force=True) | ||
|
|
||
|
|
||
| class FormConfigResponseModel(BaseModel): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import enum | ||
|
|
||
| from pydantic import BaseModel, EmailStr | ||
| from starlette.requests import Request | ||
|
|
||
| from piccolo_admin.endpoints import FormConfig | ||
|
|
||
|
|
||
| # An example of using Python enum in custom forms | ||
| class Permission(str, enum.Enum): | ||
| admissions = "admissions" | ||
| gallery = "gallery" | ||
| notices = "notices" | ||
| uploads = "uploads" | ||
|
|
||
|
|
||
| class NewStaffModel(BaseModel): | ||
| username: str | ||
| email: EmailStr | ||
| superuser: bool | ||
| permissions: Permission | ||
|
|
||
|
|
||
| def new_staff_endpoint(request: Request, data: NewStaffModel) -> str: | ||
| # We need to do the enum type conversion ourselves like this: | ||
| # data.permissions = Permission(int(data.permissions)) # for int enum | ||
| # data.permissions = Permission(data.permissions) # for str enum | ||
| print(data) | ||
| return "A new staff member has been successfully created." | ||
|
|
||
|
|
||
| FORM = FormConfig( | ||
| name="Enum form", | ||
| pydantic_model=NewStaffModel, | ||
| endpoint=new_staff_endpoint, | ||
| description="Make a enum form.", | ||
| form_group="Text forms", | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import typing as t | ||
|
|
||
|
|
||
| def convert_enum_to_choices(enum_data: t.Any) -> t.Dict[str, t.Any]: | ||
| choices = {} | ||
| for item in enum_data: | ||
| choices[item.name] = { | ||
| "display_name": item.name, | ||
| "value": item.value, | ||
| } | ||
| return choices |
Uh oh!
There was an error while loading. Please reload this page.