sqlmodel icon indicating copy to clipboard operation
sqlmodel copied to clipboard

Convert all fields to optional

Open nickleman opened this issue 4 years ago • 5 comments

First Check

  • [X] I added a very descriptive title to this issue.
  • [X] I used the GitHub search to find a similar issue and didn't find it.
  • [X] I searched the SQLModel documentation, with the integrated search.
  • [X] I already searched in Google "How to X in SQLModel" and didn't find any information.
  • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [X] I already checked if it is not related to SQLModel but to Pydantic.
  • [X] I already checked if it is not related to SQLModel but to SQLAlchemy.

Commit to Help

  • [X] I commit to help with one of those options 👆

Example Code

class HeroBase(SQLModel):
    name: str
    secret_name: str
    age: Optional[int] = None

class HeroUpdate(HeroBase, all_optional=True):
    pass

Description

Is it possible to add the ability to modify the fields of a base class to convert them to all optional with a parameter like the table=True but in this case all_optional=True? This would help eliminate the duplication when creating a class for making updates.

Wanted Solution

Set all base fields to Optional based on keyword argument.

Wanted Code

class HeroBase(SQLModel):
    name: str
    secret_name: str
    age: Optional[int] = None

class HeroUpdate(HeroBase, all_optional=True):
    pass

Alternatives

No response

Operating System

Linux, Windows

Operating System Details

No response

SQLModel Version

0.0.4

Python Version

3.8.5

Additional Context

No response

nickleman avatar Aug 31 '21 20:08 nickleman

This is pydantic-related. You can make optional fields required in child classes, but you cannot make required fields optional.

Maybe the following resources will help you:

  • https://github.com/samuelcolvin/pydantic/issues/1141#issuecomment-571247696
  • https://stackoverflow.com/a/65907609/3778854

You can use a pattern like this instead:

class HeroBase(SQLModel):
    # optional, aka nullable
    name: Optional[str]
    secret_name: Optional[str]
    age: Optional[int]

class HeroCreate(HeroBase):
    # all required
    name: str
    secret_name: str
    age: int

class HeroUpdate(HeroBase):
    pass

visini avatar Sep 01 '21 13:09 visini

You can make optional fields required in child classes, but you cannot make required fields optional.

Perhaps this is not possible with class, however I think it is possible with type()?

In https://github.com/tiangolo/sqlmodel/issues/166 I link to a proposed method, make_updater_cls, that does this.

I am new to Pydantic + SQLModel so certainly welcome any feedback on this approach.

Edit: Upon closer consideration, I realize that my proposed method does not allow for making required fields optional on a class which inherits from the user-defined base model. Rather, a new class (which inherits directly from SQLModel) is created using the user-defined base model as reference. So the more general point about Python inheritance (child classes can't "optionalize" fields) is not disproved, but perhaps the practical application (how to generate an updater model from a base model) may still be possible.

cisaacstern avatar Nov 24 '21 23:11 cisaacstern

I really find interesting the idea of creating a schema that inherits all fields from a SQLModel but make all of them Optional. Did you ever find a solution to this, @cisaacstern or @nickleman?

FilipeMarch avatar Dec 07 '22 06:12 FilipeMarch

Also - it would be cool to have better control of which field should be optional and which not.

I was thinking about some kind of "decorator" mechanism to generate desired new class similar to this:

@Partial
class Hero(SQLModel):
    id: int 
    @option
    name: str
    @option
    secret_name: str
    @remove
    age: Optional[int] = None

Above code should generate 2 classes, first one with name Hero and the second one, like this:

class HeroPartial(SQLModel):
    id: int
    name: Optional[str]
    secret_name: Optional[str]

glimanowka-dyvenia avatar Feb 12 '24 21:02 glimanowka-dyvenia

@FilipeMarch apologies, I somehow missed your ping initially, and now a huge amount of time has passed. I have not thought about this issue in a while, but yes, the solution for a make_updater_cls method, proposed in my comment above, did work for me at the time.

cisaacstern avatar Feb 23 '24 00:02 cisaacstern