You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Support mix of concrete inheritance and pydantic mixin #877
Is your feature request related to a problem? Please describe.
When defining an ormar.Model and inheriting from both an abstract ormar.Model and a mixin (pydantic in my case), two problems arise:
Two database tables are generated (e.g. "nation" and "nations"), both with the mixin fields missing.
Describe the solution you'd like
Modifications to the inheritance design so that the resulting model is working and non-abstract.
Describe alternatives you've considered
Using abstract ormar.Model instead of pydantic BaseModel for the Create, Read and Update classes (if I understood everything correctly, I have to use ormar Fields anyway and the validation should still work). I don't know how much parsing/validation overhead I am adding with this though.
EDIT: just tried it and it does not work since an abstract ormar.Model can of course not be instantiated and thus not used for validation 🤦♂️
UPDATE: I must have made some kind of mistake; I can only recreate one of my findings on second try: the mixin fields don't appear in the final tables. I've updated the issue accordingly.
Update: just discovered that if your mixin model doesn't inherit from any parent model (or at least not from a pydantic BaseModel), the combination actually works. Makes sense that there's interference if one considers how much pydantic stuff is already fused into ormar.Model. I updated the title to reflect this.
Some gripes I have:
It seems to be neither documented nor tested that a combination of ("vanilla") mixin and concrete inheritance is possible, even though this might be a useful application.
After studying the process for a bit, I am now fairly certain of what happens and what has to be done to support the desired behaviour :
In ormar.models.metaclass.extract_from_parents_definition(), a check happens whether the given base class has potential fields to copy to the new model.
Said check assumes that the fields would be immediately visible in base_class.__dict__, not nested in the __fields__ key as they are in pydantic BaseModels
Therefore no fields to add are found and the resulting model doesn't get them
One would have to check if the base_class in question is a subclass of pydantic.BaseModel and then extract the fields in a different manner, probably by calling base_class.__fields__
The last point is what I'm now trying to do but tbh it requires some deeper knowledge of how BaseModels, ormar.Models and classes in general work in order not to make mistakes and I must admit that I do not have that knowledge quite yet. Will continue my work tomorrow
Problem: pydantic automatically converts ormar Fields to pydantic Fields upon model creation, so the added information in ormar Fields is lost if I am not mistaken. That would mean my desired behaviour could only be achieved by hacky solutions, something I'd like to avoid. Maybe I'll just go the other way round and start with the model with all the fields (table model) and generate the CRUD models from it using get_pydantic(exclude={fields_i_dont_need_here}).
Activity
iron3oxide commentedon Oct 21, 2022
Sadly I haven't been able to fully understand how both these mechanisms of inheriting work in ormar, otherwise I would attempt to fix it myself..
[-]Support mix of concrete inheritance and mixin[/-][+]Support mix of concrete inheritance and pydantic mixin[/+]iron3oxide commentedon Oct 21, 2022
Update: just discovered that if your mixin model doesn't inherit from any parent model (or at least not from a pydantic BaseModel), the combination actually works.
Makes sense that there's interference if one considers how much pydantic stuff is already fused into ormar.Model. I updated the title to reflect this.Some gripes I have:
iron3oxide commentedon Oct 22, 2022
After studying the process for a bit, I am now fairly certain of what happens and what has to be done to support the desired behaviour :
ormar.models.metaclass.extract_from_parents_definition(), a check happens whether the given base class has potential fields to copy to the new model.base_class.__dict__, not nested in the__fields__key as they are in pydantic BaseModelsbase_class.__fields__The last point is what I'm now trying to do but tbh it requires some deeper knowledge of how BaseModels, ormar.Models and classes in general work in order not to make mistakes and I must admit that I do not have that knowledge quite yet. Will continue my work tomorrow
iron3oxide commentedon Oct 22, 2022
Problem: pydantic automatically converts ormar Fields to pydantic Fields upon model creation, so the added information in ormar Fields is lost if I am not mistaken. That would mean my desired behaviour could only be achieved by hacky solutions, something I'd like to avoid. Maybe I'll just go the other way round and start with the model with all the fields (table model) and generate the CRUD models from it using get_pydantic(exclude={fields_i_dont_need_here}).