Django

Code

Ticket #6844 (closed: fixed)

Opened 9 months ago

Last modified 9 months ago

Generic relations improperly inherited

Reported by: cide@ctmod.net Assigned to: nobody
Milestone: Component: Database layer (models, ORM)
Version: queryset-refactor Keywords:
Cc: Triage Stage: Unreviewed
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

As can be seen below, the generic_models attribute of the BaseModel? class is not properly inherited by the child class. In the TestModel? example where no inheritance takes place, it works fine.

Code:

from django.db import models
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType

class GenericModel(models.Model):
    # Generic relation-related attributes
    content_type = models.ForeignKey(ContentType)
    content_object = generic.GenericForeignKey()
    object_id = models.PositiveIntegerField()

class BaseModel(models.Model):
    generic_models = generic.GenericRelation(GenericModel)
    
    class Meta:
        abstract = True
        
class ChildModel(BaseModel):
    name = models.CharField(max_length=31)
        
class TestModel(models.Model):
    generic_models = generic.GenericRelation(GenericModel)

Test case:

>>> test_child = TestModel()
>>> test_child.generic_models # Works
<django.contrib.contenttypes.generic.GenericRelatedObjectManager object at 0x01FBCED0>
>>> child = ChildModel(name='Test')
>>> child.generic_models # Raises AttributeError

D:\Python25\lib\site-packages\django\contrib\contenttypes\generic.py in __get__(self, instance, instance_type)
    190             join_table = qn(self.field.m2m_db_table()),
    191             source_col_name = qn(self.field.m2m_column_name()),
--> 192             target_col_name = qn(self.field.m2m_reverse_name()),
    193             content_type = ContentType.objects.get_for_model(self.field.model),
    194             content_type_field_name = self.field.content_type_field_name,

D:\Python25\lib\site-packages\django\contrib\contenttypes\generic.py in m2m_reverse_name(self)
    132
    133     def m2m_reverse_name(self):
--> 134         return self.model._meta.pk.column
    135
    136     def contribute_to_class(self, cls, name):

AttributeError: 'NoneType' object has no attribute 'column'

Attachments

generic_relations_inheritance.diff (0.7 kB) - added by cide@ctmod.net on 03/20/08 16:18:53.
Patch that locally fixes the issue

Change History

03/20/08 16:18:53 changed by cide@ctmod.net

  • attachment generic_relations_inheritance.diff added.

Patch that locally fixes the issue

03/20/08 16:20:55 changed by cide@ctmod.net

  • needs_better_patch changed.
  • has_patch set to 1.
  • needs_tests changed.
  • needs_docs changed.

I have attached a patch that locally fixes the issue. As far as I can tell, inherited classes m2m fields were not added to the class. However, my experience with django's internals is limited at best, so someone definitely needs to look over the patch and make sure it works.

03/21/08 10:58:50 changed by mtredinnick

Well done on finding the cause! There's some tricky code to navigate there.

The patch is almost correct. There's no need to loop over anything more than _meta.local_many_to_many, however, which is a little faster. So we'll do that.

03/21/08 11:06:41 changed by mtredinnick

  • status changed from new to closed.
  • resolution set to fixed.

(In [7345]) queryset-refactor: Correctly inherit m2m fields from abstract base classes. Based on a patch from cide@ctmod.net. Fixed #6844.


Add/Change #6844 (Generic relations improperly inherited)




Change Properties
Action