pydantic: Model with field name that shadows existing BaseModel attribute leads to unexpected behavior
Hello, First of all this is an awesome project, I want to use it in all my tools đ.
I ran into a small issue: when defining a model that has a field with the same name as one of BaseModelâs existing attributes/methods, the field gets parsed but cannot be retrieved:
class BadModel(BaseModel):
schema: str
obj = BaseModel(**{'schema': 'abc'})
print(obj.schema)
This prints <bound method BaseModel.schema of <class 'pydantic.main.BaseModel'>>
instead of abc
.
This makes perfect sense when looking at the code but is a bit unexpected. To be honest, Iâm not sure what the ârightâ behavior should be here?
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 15 (12 by maintainers)
Well, that kind of shadowing isnât compatible with type checking in Python; you cannot have a field with a disparate type on a sub-model. You can define your class methods on the metaclass so that they are not present on instances of
Users
but your type checker (assuming you use one) wonât know what to do with them either:Anyway, this will work without requiring any changes to
Pydantic
, assuming that you donât step on any of its own methods.@layday thanks I have seen that interesting thread. But that discussion is more around public instance variables as opposed to class variable vs instance variable shadowing. Obviously you wouldnât want to remove the
utils.validate_field_name
at this point since its been there since 0.12. But if we can pass inconfig: Type['BaseConfig']
and make it a config property so we can control the shadow behavior from a config that would be a flexible solution.I am a bit surprised this PR made it into pydantic. Think about building an ORM. Imagine all of your pydantic models (like Users in the example below) extend your own base
Model
class which had classmethods offind()
,where()
, andget()
. This allows you to use your model in an ORM fasion like so.All fine, until the user wants a field called
find
, orwhere
, orget
etc⌠I understand they can set the field toget_
and use a alias for the actual db column namedget
but this seems an ugly hack when you could have just allowed shadowing.With the above PR
utils.validate_field_name
will throw a shadow error if the user wants fields calledfind
orwhere
orget
etc⌠Your main argument is that itâs âconfusingâ the difference betweenUsers.find
anduser.find
. Well, they are two completely different things, and should be allowed. Shadowing is an important part of any language and is a powerful tool when dealing with class variables vs instance variables. My only option at this point is to maintain a fork or pydantic which removes thisvalidate_field_name
method completely so I can build a nice ORM without working about stomping all over the users âfieldâ namespace.Oh thanks, let me look into aliases. If that works then an exception seems fine.