Skip to content

Support mix of concrete inheritance and pydantic mixin #877

Open

Description

@iron3oxide

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:

  1. The resulting model is abstract by default, see Model inheriting from abstract models is abstract by default #876 (couldn't edit the issue sufficiently so I decided to reference it here)
  2. 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.

Activity

  1. iron3oxide commented on Oct 21, 2022

    @iron3oxide
    Author

    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..

  2. changed the title [-]Support mix of concrete inheritance and mixin[/-] [+]Support mix of concrete inheritance and pydantic mixin[/+] on Oct 21, 2022
  3. iron3oxide commented on Oct 21, 2022

    @iron3oxide
    Author

    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:

    1. 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.
    2. I still can't reuse my pydantic CRUD models.
  4. iron3oxide commented on Oct 22, 2022

    @iron3oxide
    Author

    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

  5. iron3oxide commented on Oct 22, 2022

    @iron3oxide
    Author

    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}).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions