Opened 11 years ago

Closed 11 years ago

Last modified 11 years ago

#20279 closed Bug (invalid)

Failure with non-standard GenericForeignKey field names

Reported by: lucemia@… Owned by: Simon Charette
Component: contrib.contenttypes Version: 1.4
Severity: Normal Keywords:
Cc: Simon Charette Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Simon Charette)

While I used field names item_type, item_id instead of content_type, object_id to reference an object. and while delete the object, it will raise exception.

For example:

class ObjectPermission(models.Model):
    # implement object/row based permission
    # it support permission for all, for table and for object
    # the item_type, item_id designed to accept 0, as a wildcard
    permission = models.ForeignKey(Permission)

    item_type = models.ForeignKey(ContentType, blank=True, default=0, null=True)
    item_id = models.PositiveIntegerField(blank=True, default=0)
    item_object = generic.GenericForeignKey('item_type', 'item_id')


class Publisher(models.Model):
    name = models.CharField(max_length=255)

I create an relation between publisher and object permission.
while delete a publisher in django admin, it will raise fielderror,

at query.py line 1320
raise FieldError("Cannot resolve keyword object into field. "
                            "Choices are: %s" % (name, ", ".join(names)))

and after I change the field name back to content_type, object_id,
the exception won't appear.

The django doc didn't mentioned this behavior

Change History (9)

comment:1 by Simon Charette, 11 years ago

Component: Uncategorizedcontrib.contenttypes
Description: modified (diff)
Resolution: needsinfo
Status: newclosed

Please re-open with the full traceback and use WikiFormating when providing code samples.

comment:2 by anonymous, 11 years ago

Test Case:

  1. create a generic relationship between object permission and publisher.
  2. delete a publisher in django admin.

The field name of generice relation will affect the behavior.

It will raise exception

class ObjectPermission(models.Model):    
    permission = models.ForeignKey(Permission)

    item_type = models.ForeignKey(ContentType, blank=True, default=0, null=True)
    item_id = models.PositiveIntegerField(blank=True, default=0)
    item_object = generic.GenericForeignKey('item_type', 'item_id')

It won't raise exception

class ObjectPermission(models.Model):    
    permission = models.ForeignKey(Permission)

    content_type = models.ForeignKey(ContentType, blank=True, default=0, null=True)
    object_id = models.PositiveIntegerField(blank=True, default=0)
    content_object = generic.GenericForeignKey('content_type', 'object_id')

debug track on

http://dpaste.com/1062740/

Last edited 11 years ago by Simon Charette (previous) (diff)

comment:3 by Simon Charette, 11 years ago

I guess you mean the item_type and type_id example will raise exception?

comment:4 by anonymous, 11 years ago

Yes it will raise exception while I named the generic relation like item type and item id

comment:5 by Simon Charette, 11 years ago

Cc: Simon Charette added
Resolution: needsinfo
Status: closednew

comment:6 by Claude Paroz, 11 years ago

Summary: generic relationFailure with non-standard GenericForeignKey field names

comment:7 by Simon Charette, 11 years ago

Owner: changed from nobody to Simon Charette
Status: newassigned

Full traceback since it will expire in 6 days. I'll try to reproduce.

Environment:


Request Method: GET
Request URL: http://localhost:8080/admin/console/publisher/1/delete/

Django Version: 1.4.2
Python Version: 2.7.2
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'django.contrib.admindocs',
 'console')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')


Traceback:
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\core\handlers\base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\contrib\admin\options.py" in wrapper
  366.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\utils\decorators.py" in _wrapped_view
  91.                     response = view_func(request, *args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\views\decorators\cache.py" in _wrapped_view_func
  89.         response = view_func(request, *args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\contrib\admin\sites.py" in inner
  196.             return view(request, *args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\utils\decorators.py" in _wrapper
  25.             return bound_func(*args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\utils\decorators.py" in _wrapped_view
  91.                     response = view_func(request, *args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\utils\decorators.py" in bound_func
  21.                 return func(self, *args2, **kwargs2)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\db\transaction.py" in inner
  209.                 return func(*args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\contrib\admin\options.py" in delete_view
  1274.             [obj], opts, request.user, self.admin_site, using)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\contrib\admin\util.py" in get_deleted_objects
  104.     collector.collect(objs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\contrib\admin\util.py" in collect
  155.             return super(NestedObjects, self).collect(objs, source_attr=source_attr, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\db\models\deletion.py" in collect
  185.                     sub_objs = relation.bulk_related_objects(new_objs, self.using)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\contrib\contenttypes\generic.py" in bulk_related_objects
  233.                     [obj.pk for obj in objs]
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\db\models\manager.py" in filter
  143.         return self.get_query_set().filter(*args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\db\models\query.py" in filter
  624.         return self._filter_or_exclude(False, *args, **kwargs)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\db\models\query.py" in _filter_or_exclude
  642.             clone.query.add_q(Q(*args, **kwargs))
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\db\models\sql\query.py" in add_q
  1250.                             can_reuse=used_aliases, force_having=force_having)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\db\models\sql\query.py" in add_filter
  1122.                     process_extras=process_extras)
File "C:\Program Files (x86)\Google\google_appengine\lib\django_1_4\django\db\models\sql\query.py" in setup_joins
  1321.                             "Choices are: %s" % (name, ", ".join(names)))

Exception Type: FieldError at /admin/console/publisher/1/delete/
Exception Value: Cannot resolve keyword 'object_id' into field. Choices are: advertiser, group, id, item_id, item_type, permission, publisher, user

comment:8 by Simon Charette, 11 years ago

Resolution: invalid
Status: assignedclosed

First I assume your Publisher model has a GenericRelation pointing to ObjectPermission and you forgot to mention it in your initial report.

As explained in the documentation:

Just as GenericForeignKey accepts the names of the content-type and object-ID fields as arguments, so too does GenericRelation;
if the model which has the generic foreign key is using non-default names for those fields, you '''must''' pass the names of the
fields when setting up a GenericRelation to it.

Thus your Publisher definition should look like that.

class Publisher(models.Model):
    name = models.CharField(max_length=255)
    permissions = generic.GenericRelation(
        ObjectPermission, content_type_field='item_type', object_id_field='item_id'
    )

I managed to reproduce the failure you reported by omitting the content_type_field and object_id_field kwargs.

Please use support channels in the future before reporting issues, I guess someone could have helped you way faster by pointing you to the doc.

Thanks for the report and let us know if that doesn't solve it for you.

comment:9 by anonymous, 11 years ago

Yes, it solved my issue. It is exactly what happened! Thank you very much!!

Note: See TracTickets for help on using tickets.
Back to Top