Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get "AttributeError: __fields_set__" when subclassing a Pydantic BaseModel?

I have this project where my base class and my sub-classes implement pydantic.BaseModel:

from pydantic import BaseModel
from typing import List
from dataclasses import dataclass

@dataclass
class User(BaseModel):
    id: int 

@dataclass
class FavoriteCar(User):
    car_names: List[str] 

car = FavoriteCar(id=1, car_names=["Acura"])
print(f"{car.id} {car.car_names[0]}")

But this error appears:

    self.__fields_set__.add(name)
E   AttributeError: __fields_set__

Does someone mind explaining what is going on? The reason why I want to use pydantic is because I need a way to quickly convert Python objects to dict (or JSON) and back.

like image 277
Kendrick Lamar Avatar asked Feb 10 '20 21:02

Kendrick Lamar


People also ask

What if I don't want to use pydantic's basemodel?

If you don't want to use pydantic 's BaseModel you can instead get the same data validation on standard dataclasses (introduced in python 3.7). Dataclasses work in python 3.6 using the dataclasses backport package.

Which pydantic field types can be used in Python?

You can use all the standard pydantic field types, and the resulting dataclass will be identical to the one created by the standard library dataclass decorator. The underlying model and its schema can be accessed through __pydantic_model__ .

How do I create a pydantic model from a class?

Pydantic models can be created from arbitrary class instances to support models that map to ORM objects. To do this: The Config property orm_mode must be set to True. The special constructor from_orm must be used to create the model instance.

Which fields require a default_factory in mypy?

Also, fields that require a default_factory can be specified by a dataclasses.field. pydantic.dataclasses.dataclass 's arguments are the same as the standard decorator, except one extra keyword argument config which has the same meaning as Config. After v1.2, The Mypy plugin must be installed to type check pydantic dataclasses.


Video Answer


2 Answers

You need to decide whether to inherit from pydantic.BaseModel, or whether to use the @dataclass decorator (either from dataclasses, or from pydantic.dataclasses).

Either is fine, but you cannot use both, according to the documentation (bold face added by myself):

If you don't want to use pydantic's BaseModel you can instead get the same data validation on standard dataclasses

like image 156
Peter Thomassen Avatar answered Oct 19 '22 06:10

Peter Thomassen


E   AttributeError: __fields_set__

The first part of your question is already answered by Peter T as Document says - "Keep in mind that pydantic.dataclasses.dataclass is a drop-in replacement for dataclasses.dataclass"

The second part is that you wanted to convert them as dict.

The reason why I want to use pydantic is because I need a way to quickly convert Python objects to dict (or JSON) and back

To answer to that part of your question you can use asdict of dataclass itself source

from dataclasses import dataclass, asdict
from typing import List


@dataclass
class Point:
     x: int
     y: int

@dataclass
class C:
     l: List[Point]

p = Point(10, 20)
assert asdict(p) == {'x': 10, 'y': 20}

c = C([Point(0, 0), Point(10, 4)])
assert asdict(c) == {'l': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}

There is discussion about these module level helper function(.asdict & .astuple) that they arent PEP8 compliant (should be as_dict() and as_tuple()) however finally they decided to keep consistency with namedtuple._asdict() and attr.asdict(). source

like image 1
Shakeel Avatar answered Oct 19 '22 05:10

Shakeel