djangopython-2.7django-modelslist-comprehensionmulti-table-inheritance

Django multi-table inheritance chokes on leaked variable in model definition


class Parent(models.Model):
    pass

class RebelliousChild(Parent):
    parent_fields = [__x.name for __x in Parent._meta._fields()]

Django 1.3 responds:

django.core.exceptions.FieldError: Local field '_RebelliousChild__x' 
in class 'RebelliousChild'clashes with field of similar name from base class 'Parent'

Django 1.5 responds:

FieldError: Local field u'id' in class 'RebelliousChild' clashes with field 
of similar name from base class 'Parent'

My second reaction (after trying to make the variable private) was to delete the variable (which worked.)

parent_fields = [__x.name for __x in Parent._meta._fields()]
del __x

List comprehensions leak their control variables in Python 2. Django prohibits overriding parent field attributes, which seems to be involved somehow, since Django 1.5 has the same issue. But in both cases the leaked attribute name _RebelliousChild__x isn't defined on Parent.

What is going on here?

PS Using "list(x.name for x in Parent._meta._fields())" is prettier than "del x". See the aforementioned https://stackoverflow.com/a/4199355 about generators not leaking their control variables.


Solution

  • Have a look here: https://docs.djangoproject.com/en/1.5/topics/db/models/#multi-table-inheritance

    In short, you don't need to apply the parent fields to the child(they already exist, but in a different table), you can access them directly on a RebelliousChild instance.