Skip to content
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

1132 If a column is nullable, make it optional by default in create_pydantic_model #1141

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

dantownsend
Copy link
Member

@dantownsend dantownsend commented Jan 14, 2025

Resolves #1132

@dantownsend dantownsend added the enhancement New feature or request label Jan 14, 2025
@Skelmis
Copy link
Collaborator

Skelmis commented Jan 16, 2025

Assuming required becoming None doesn't break the admin panels behavior I like the look of this

@sinisaos
Copy link
Member

I agree with these changes and everything works, but we have one case where someone makes a mistake and marks a null field as optional. We have four options.

class Band(Table):
    name = Varchar() # null=False by default

>>> create_pydantic_model(Band).model_fields['name'].annotation
str # correct

class Band(Table):
    name = Varchar(null=True)

>>> create_pydantic_model(Band).model_fields['name'].annotation
Optional[str] # correct

class Band(Table):
    name = Varchar(required=True, null=True)

>>> create_pydantic_model(Band).model_fields['name'].annotation
str # correct

class Band(Table):
    name = Varchar(required=False) # null=False by default

>>> create_pydantic_model(Band).model_fields['name'].annotation
Optional[str] # not correct, should be str (required because is not null constraint in db)

Should we prevent these possible user errors or not? If we change this line of code, we can force required to be True if null is False, to prevent user errors. After that change result is

class Band(Table):
    name = Varchar(required=False) # null=False by default

>>> create_pydantic_model(Band).model_fields['name'].annotation
str # correct

which is correct.

@dantownsend
Copy link
Member Author

@Skelmis and @sinisaos - thanks for your feedback on this.

I've been thinking about it today, and I'm a bit undecided still.

Current behaviour

The current behaviour in Piccolo is required=False by default, which means that if we have this:

class Band(Table):
    name = Varchar()

The it generates the following Pydantic model:

class BandModel(BaseModel):
    name: Optional[str]

In terms of generating the Pydantic model, null is completely ignored, it's completely driven by required.

This is similar to Django where they have nullable and blank arguments. Only blank determines if the field is required in Django Admin.

Maybe we should have made required=True the default - it's hard to say.

Multiple Pydantic models

The downside with putting required on the Piccolo Table is that you will often have multiple Pydantic models per table. For example:

  1. A model for filtering or PATCH (where every field is optional)
  2. A model for returning data in a GET request, or receiving a POST (where some fields will be required)

We get around 1 by having the all_optional argument in create_pydantic_model.

create_pydantic_model(
    Band,
    all_optional=True
)

If someone required even more Pydantic models from the same Piccolo table it gets tricky. Perhaps there could be a required_columns arg in create_pydantic_model:

create_pydantic_model(
    Band,
    required_columns=Band.all_columns(exclude=[Band.some_column])
)

That gives the ultimate flexibility.

Conclusions (?)

I'm still a bit on the fence ... I'm interested to hear your thoughts.

I think I'll refactor piccolo-orm/piccolo_admin#432 slightly for now, so it's decoupled from this PR, as I don't want to rush this in and make a mistake.

@dantownsend
Copy link
Member Author

>>> create_pydantic_model(Band).model_fields['name'].annotation
Optional[str] # not correct, should be str (required because is not null constraint in db)

@sinisaos I think for that situation we just assume that the user will add the missing value before saving it to the database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: In progress
Development

Successfully merging this pull request may close these issues.

create_pydantic_model returns models with wrong fields marked as null
3 participants