#34634: Creating objects with nested MTI crashes.
-------------------------------------+-------------------------------------
Reporter: Mariusz Felisiak | Owner: Akash
| Kumar Sen
Type: Bug | Status: assigned
Component: Database layer | Version: 4.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Akash Kumar Sen):
Possible MTI Scenarios with two bases in Django
**Example Model:**
{{{
class CommonChild(FirstParent, SecondParent):
pass
}}}
**Case 1 -- FirstParent and Secondparent are does not have a common
ancestor**
- This scenario shows no regression
**Case 2 -- FirstParent and Secondparent have a common ancestor**
- This scenario shows regression only with primary key with default, as
mentioned in #33414
**Case 3 -- FirstParent is the ancestor of SecondParent**
- This shows the following {{{TypeError}}}. (I think this is the expected
scenario)
{{{
TypeError: Cannot create a consistent method resolution
order (MRO) for bases FirstParent, Secondparent
}}}
**Case 4 -- Secondparent is the ancestor of FirstParent(Case mentioned
here)**
- I tried to print {{{ItalianRestaurantManyParents._meta.get_fields()}}} ,
it contained all the fields of the {{{Place}}} model twice, that means we
are having conflicts passing all the checks here.
- As the fields in {{{ItalianRestaurantManyParents}}} is already a
superset of all the fields of {{{Place}}} I don't think it makes any real
world use case scenario for allowing such this kind of MTI scenario.
- **Possible solution 1 :** would be to put a check and show a similar
kind of error like case 3.
- **Possible solution 2 :** would be to let the child eat the parent
during initialization of the model, like the following. (This seems to be
passing all the tests, just have one problem. When the user defines a
custom {{{OneToOneField}}} pointer to the SecondParent)
{{{
class ModelBase(type):
"""Metaclass for all models."""
def __new__(cls, name, bases, attrs, **kwargs):
super_new = super().__new__
# Also ensure initialization is only performed for subclasses of
Model
# (excluding Model class itself).
parents = [b for b in bases if isinstance(b, ModelBase)]
for parent in parents:
if any(
issubclass(other_parent, parent)
for other_parent in parents
if not other_parent == parent
):
parents.remove(parent)
if not parents:
return super_new(cls, name, bases, attrs)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34634#comment:8>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070188b4bfb264-4103e90a-f0c4-4564-b550-1d39448ca0a7-000000%40eu-central-1.amazonses.com.