Django

Code

Ticket #8309 (closed: fixed)

Opened 4 months ago

Last modified 3 months ago

GenericForeignKey fails when used in abstract base models

Reported by: Wonlay Assigned to: jacob
Milestone: 1.0 Component: Contrib apps
Version: SVN Keywords: GenericForeignKey , model inheritance
Cc: carl@dirtcircle.com, wonlay@gmail.com, albrecht.andi@gmail.com, gonz@webstudio.com.uy Triage Stage: Accepted
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

The following code will reproduce this bug:

# aaa/models.py
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class MyModel(models.Model):
	field = models.IntegerField()

class TaggedItemBase(models.Model):
	class Meta:
		abstract = True

	content_type = models.ForeignKey(ContentType)
	object_id = models.PositiveIntegerField()

	content_object = generic.GenericForeignKey()

class TaggedItem(TaggedItemBase):
	"""A tag on an item."""
	tag = models.SlugField()

	class Meta:
		ordering = ["tag"]

	def __unicode__(self):
		return self.tag


# From command shell
>>> from aaa.models import MyModel, TaggedItem
>>> m = MyModel(field=1)
>>> m.save()
>>> t = TaggedItem(content_object=m, tag="my")
Traceback (most recent call last):
  File "<console>", line 1, in ?
  File "/usr/lib/python2.4/site-packages/django/db/models/base.py", line 240, in __init__
    raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
TypeError: 'content_object' is an invalid keyword argument for this function

If we do not use model inheritance, the script works fine.

Attachments

genericforeignkey_fail_in_abstract_models_r8507.diff (4.9 kB) - added by msaelices on 08/23/08 18:47:28.
Patch that fixes problem (with tests)

Change History

08/14/08 08:59:49 changed by mtredinnick

  • needs_better_patch changed.
  • needs_docs changed.
  • stage changed from Unreviewed to Accepted.
  • needs_tests changed.
  • milestone changed from 1.0 beta to 1.0.

08/14/08 12:12:41 changed by carljm

  • cc set to carl@dirtcircle.com.

08/14/08 22:35:45 changed by Wonlay

  • cc changed from carl@dirtcircle.com to carl@dirtcircle.com, wonlay@gmail.com.

It may caused by:

GenericForeignKey?.contribute_to_class is called on TaggedItemBase?(not on TaggedItem?), and register a signal pre_init.

When initialize the subclass TaggedItem?, the signal does not fire.

08/15/08 00:14:49 changed by Wonlay

I found that 'content_object' is not in TaggedItem.__dict__, missing due to inheritance?

08/16/08 11:28:10 changed by aalbrecht

  • cc changed from carl@dirtcircle.com, wonlay@gmail.com to carl@dirtcircle.com, wonlay@gmail.com, albrecht.andi@gmail.com.

08/23/08 17:14:36 changed by msaelices

  • owner changed from nobody to msaelices.

08/23/08 17:14:42 changed by msaelices

  • status changed from new to assigned.

08/23/08 17:18:55 changed by msaelices

Real problem is in this fragment of django.db.base.ModelBase class:

                # The abstract base class case.
                names = set([f.name for f in new_class._meta.local_fields + new_class._meta.many_to_many])
                for field in base._meta.local_fields + base._meta.local_many_to_many:
                    if field.name in names:
                        raise FieldError('Local field %r in class %r clashes with field of similar name from abstract base class %r'
                                % (field.name, name, base.__name__))
                    new_class.add_to_class(field.name, copy.deepcopy(field))

The problem is django.contrib.generic.GenericForeignKey.contribute_to_class doesnt call to cls._meta.add_field(self), that insert field into base._meta.local_fields.

But the thing is GenericForeignKey is not a real field... is a virtual field. I'll try take a workaround that also implements a new feature, for adding virtual fields thats follow inheritance.

08/23/08 18:47:28 changed by msaelices

  • attachment genericforeignkey_fail_in_abstract_models_r8507.diff added.

Patch that fixes problem (with tests)

08/23/08 19:25:25 changed by msaelices

  • has_patch set to 1.

08/25/08 22:54:27 changed by anonymous

msaelices's patch works fine for me?
Is it time to check in?

08/26/08 03:29:04 changed by msaelices

I'm not a core dev, I think patch works and of course pass all model tests. If a core developer think patch is good, he will check in as soon as possible (it's scheduled for 1.0)

08/26/08 16:03:48 changed by anonymous

  • cc changed from carl@dirtcircle.com, wonlay@gmail.com, albrecht.andi@gmail.com to carl@dirtcircle.com, wonlay@gmail.com, albrecht.andi@gmail.com, gonz@webstudio.com.uy.

09/02/08 09:29:41 changed by jacob

  • owner changed from msaelices to jacob.
  • status changed from assigned to new.

09/02/08 09:29:44 changed by jacob

  • status changed from new to assigned.

09/02/08 10:26:01 changed by jacob

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

(In [8855]) Fixed #8309: subclasses now inherit GenericForeignKey correctly. There's also now an internal API so that other "virtual fields" like GFK can be inherited as well. Thanks, msaelices.


Add/Change #8309 (GenericForeignKey fails when used in abstract base models)




Change Properties
Action