I partially answered it here: Initialize FastAPI BaseModel using non-keywords arguments (a.k.a *args) but I'll give here more dynamic options.
Option 1: use the order of the attributes
Your case has the problem that Pydantic does not maintain the order of all fields (depends at least on whether you set the type). If you specify the type of name
then this works:
from pydantic import BaseModel
from datetime import date
class User(BaseModel):
id: int
name: str = 'John Doe'
sex: str
money: float = None
dt: date
def __init__(self, *args):
# Get a "list" of field names (or key view)
field_names = self.__fields__.keys()
# Combine the field names and args to a dict
# using the positions.
kwargs = dict(zip(field_names, args))
super().__init__(**kwargs)
data = [1, 'Tike Myson', 'male', None, '2022-01-20']
user = User(*data)
Option 2: set the order as class variable
This has the downside of not being as dynamic but does not have the problem of the order being undesirable.
from pydantic import BaseModel
from datetime import date
class User(BaseModel):
id: int
name = 'John Doe'
sex: str
money: float = None
dt: date
field_names: ClassVar = ('id', 'name', 'sex', 'money', 'dt')
def __init__(self, *args):
# Combine the field names and args to a dict
# using the positions.
kwargs = dict(zip(self.field_names, args))
super().__init__(**kwargs)
data = [1, 'Tike Myson', 'male', None, '2022-01-20']
user = User(*data)
Option 3: just hard-code them in the __init__
This is similar to option 2 but a bit simple (and less reusable).
from pydantic import BaseModel
from datetime import date
from typing import ClassVar
class User(BaseModel):
id: int
name = 'John Doe'
sex: str
money: float = None
dt: date
def __init__(self, id, name, sex, money, dt):
super().__init__(id=id, name=name, sex=sex, money=money, dt=dt)
data = [1, 'Tike Myson', 'male', None, '2022-01-20']
user = User(*data)
Option 4: Without overriding
One more solution but this does not require overriding the __init__
. However, this requires more code when creating an instance:
from pydantic import BaseModel
from datetime import date
class User(BaseModel):
id: int
name = 'John Doe'
sex: str
money: float = None
dt: date
data = [1, 'Tike Myson', 'male', None, '2022-01-20']
# Combine the field names and data
field_names = ['id', 'name', 'sex', 'money', 'dt']
kwargs = dict(zip(field_names, data))
# Create an instance of User from a dict
user = User(**kwargs)
Note for options 1, 2 & 3
If you have multiple places where you need this, create a base class that has the __init__
overridden and subclass that.