Opened 18 years ago

Closed 3 years ago

#2316 closed Bug (duplicate)

GenericRelation and get_or_create do not work together

Reported by: Rudolph Froger Owned by: Adrian Holovaty
Component: contrib.contenttypes Version: dev
Severity: Normal Keywords: GenericRelation
Cc: jonozzz Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I think GenericRelation and get_or_create do not work together. Example:

baz = Bar.objects.get_or_create(content_object=foo)

You get an exception:
Cannot resolve keyword 'content_object' into field

Attachments (3)

generic_patch.diff (413 bytes ) - added by slevcom1@… 17 years ago.
patch to fix get_or_create with GenericRelation
generic_patch.2.diff (594 bytes ) - added by slevcom1@… 17 years ago.
other patch had problems, this one works better
0001-Fixed-2316-Added-get_or_create-to-GenericRelatedObje.diff (2.7 KB ) - added by Henrique Bastos 13 years ago.
Updated patch with tests

Download all attachments as: .zip

Change History (26)

comment:1 by David Danier <goliath.mailinglist@…>, 17 years ago

If I see this right this does not work with any operation (get, filter, exclude, ...) and is so far not intended to be used this way.
(I think this bug targets models.GenericForeignKey, as there is no code-example provided)

Ugly workaround (thats the reason I posted in the first place ;-):

from django.contrib.contenttypes.models import ContentType
baz = Bar.objects.get_or_create(content_type=ContentType.objects.get_for_model(foo.__class__),
                                object_id=getattr(foo, foo.__class__._meta.pk.column))

Somehow nicer (but unflexible in this form):

def do_generic_stuff(func, obj):
    from django.contrib.contenttypes.models import ContentType
    content_type = ContentType.objects.get_for_model(obj.__class__)
    object_id = getattr(obj, obj.__class__._meta.pk.column)
    return func(content_type=content_type, object_id=object_id)

# call:
baz = do_generic_stuff(Bar.objects.get_or_create, foo)
Last edited 13 years ago by Luke Plant (previous) (diff)

comment:2 by (none), 17 years ago

milestone: Version 1.0

Milestone Version 1.0 deleted

comment:3 by slevcom1@…, 17 years ago

Component: Admin interfaceCore framework
Has patch: set
Keywords: GenericRelation added
Needs tests: set
Resolution: fixed
Status: newclosed

I created a simple patch for this. It seems to work for me.

by slevcom1@…, 17 years ago

Attachment: generic_patch.diff added

patch to fix get_or_create with GenericRelation

by slevcom1@…, 17 years ago

Attachment: generic_patch.2.diff added

other patch had problems, this one works better

comment:4 by Simon G. <dev@…>, 17 years ago

Triage Stage: UnreviewedAccepted

comment:5 by Chris Beaven, 16 years ago

Resolution: fixed
Status: closedreopened

This was never fixed (slevcom1: posting a working patch is fine, but until it's in svn the ticket stays open)

Check out #3121 for a related ticket.

comment:6 by Chris Beaven, 16 years ago

Resolution: duplicate
Status: reopenedclosed

In fact, I just tried #3121 and that works fine. So I'll close this as a dupe.

comment:7 by wam, 14 years ago

Resolution: duplicate
Status: closedreopened
Version: SVN1.1

This bug is neither a duplicate nor has it been fixed. Using Django 1.1.1, the issue still persists, as demonstrated by:

# Model definition for app ticket2316 demonstrating bug #2316
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class SomeObject(models.Model):
    test_content_type = models.ForeignKey(ContentType, null=True, blank=True)
    test_object_id = models.PositiveIntegerField(null=True, blank=True)
    test_object = generic.GenericForeignKey('test_content_type', 'test_object_id')

After the customary syncdb, etc:

>>> from ticket2316.models import SomeObject
>>> from  django.contrib.auth.models import User
>>> User.objects.all()[0]
<User: wam>
>>> user = _
>>> SomeObject(test_object=user)
<SomeObject: SomeObject object>
>>> SomeObject.objects.get_or_create(test_object=user)
------------------------------------------------------------
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/wam/projs/virtualenvs/demo/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg/django/db/models/manager.py", line 123, in get_or_create
    return self.get_query_set().get_or_create(**kwargs)
  File "/home/wam/projs/virtualenvs/demo/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg/django/db/models/query.py", line 328, in get_or_create
    return self.get(**kwargs), False
  File "/home/wam/projs/virtualenvs/demo/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg/django/db/models/query.py", line 299, in get
    clone = self.filter(*args, **kwargs)
  File "/home/wam/projs/virtualenvs/demo/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg/django/db/models/query.py", line 498, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/home/wam/projs/virtualenvs/demo/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg/django/db/models/query.py", line 516, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/home/wam/projs/virtualenvs/demo/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg/django/db/models/sql/query.py", line 1675, in add_q
    can_reuse=used_aliases)
  File "/home/wam/projs/virtualenvs/demo/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg/django/db/models/sql/query.py", line 1569, in add_filter
    negate=negate, process_extras=process_extras)
  File "/home/wam/projs/virtualenvs/demo/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg/django/db/models/sql/query.py", line 1737, in setup_joins
    "Choices are: %s" % (name, ", ".join(names)))
<class 'django.core.exceptions.FieldError'>: Cannot resolve keyword 'test_object' into field. Choices are: id, test_content_type, test_object_id

I'll try and work up a more formal unittest in the near future.

P.S. I don't exactly know how I should change the properties, considering this ticket has remained dormant for the past two years. I considered filing a new ticket, but the problem is *exactly* the failure condition this ticket was originally opened to address, it just appears the ticket got diverted onto a tangent with a similar, but not identical ticket that the original poster may have been experiencing as well.

comment:8 by jonozzz, 14 years ago

Cc: jonozzz added

comment:9 by jonozzz, 14 years ago

milestone: 1.3
Version: 1.11.2

Looks like this one missed another milestone, 1.2 is out and this totally legit patch didn't make it through.
Is anyone going to submit it into the SVN ?

in reply to:  9 comment:10 by Karen Tracey, 14 years ago

Replying to jonozzz:
Note it's not necessary to change version to a higher number when releases go out. The version field is supposed to reflect what version of code was in use when the problem was reported (or the feature requested). When accurate, it gives a clue of how old the reported behavior is; updating it to be a higher number is rarely correct. It is not a target release for fixing the problem/implementing the feature: that's what milestone is for.

comment:11 by Alex Gaynor, 14 years ago

Component: Core frameworkContrib apps

by Henrique Bastos, 13 years ago

Updated patch with tests

comment:12 by Henrique Bastos, 13 years ago

Needs tests: unset

Just updated the patch to the current state of the ORM and added some tests.

comment:13 by Luke Plant, 13 years ago

Has patch: unset

The attached patch does not address the original problem, as can be seen if you change this line in the added test:

   fatty = TaggedItem.objects.create(content_object=bacon, tag="fatty")

to:

   fatty = TaggedItem.objects.get_or_create(content_object=bacon, tag="fatty")

The patch fixes a related problem, which is probably worthy of fixing on its own, although the original bug title would cover both cases.

The original bug would probably require patching core, or we might want to wait until core has support for virtual/composite fields and GenericRelations could be re-worked to use that support.

So, the most recent patch needs to be put into a new ticket if it is to be included on its own. So I'm marking *this* ticket as having no patch.

Sorry for the ticket-churn, but it's needed to keep things sane. Thanks.

comment:14 by Gabriel Hurley, 13 years ago

Component: Contrib appscontrib.contenttypes

comment:15 by Łukasz Rekucki, 13 years ago

Type: defectBug

comment:16 by Łukasz Rekucki, 13 years ago

Severity: normalNormal

comment:17 by Jacob, 12 years ago

milestone: 1.3

Milestone 1.3 deleted

comment:11 by Aymeric Augustin, 12 years ago

UI/UX: unset

Change UI/UX from NULL to False.

comment:12 by Aymeric Augustin, 12 years ago

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:13 by Aymeric Augustin, 11 years ago

Status: reopenednew

comment:14 by anonymous, 11 years ago

well i want to check if its good for my needs

comment:15 by Asif Saifuddin Auvi, 8 years ago

Version: 1.2master

comment:16 by Mariusz Felisiak, 3 years ago

Resolution: duplicate
Status: newclosed
Note: See TracTickets for help on using tickets.
Back to Top