Code

Opened 8 years ago

Last modified 8 months ago

#2316 new Bug

GenericRelation and get_or_create do not work together

Reported by: Rudolph Owned by: adrian
Component: contrib.contenttypes Version: 1.2
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@… 7 years ago.
patch to fix get_or_create with GenericRelation
generic_patch.2.diff (594 bytes) - added by slevcom1@… 7 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 henriquebastos 3 years ago.
Updated patch with tests

Download all attachments as: .zip

Change History (24)

comment:1 Changed 7 years ago by David Danier <goliath.mailinglist@…>

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 3 years ago by lukeplant (previous) (diff)

comment:2 Changed 7 years ago by anonymous

  • milestone Version 1.0 deleted

Milestone Version 1.0 deleted

comment:3 Changed 7 years ago by slevcom1@…

  • Component changed from Admin interface to Core framework
  • Has patch set
  • Keywords GenericRelation added
  • Needs tests set
  • Resolution set to fixed
  • Status changed from new to closed

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

Changed 7 years ago by slevcom1@…

patch to fix get_or_create with GenericRelation

Changed 7 years ago by slevcom1@…

other patch had problems, this one works better

comment:4 Changed 7 years ago by Simon G. <dev@…>

  • Triage Stage changed from Unreviewed to Accepted

comment:5 Changed 6 years ago by SmileyChris

  • Resolution fixed deleted
  • Status changed from closed to reopened

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 Changed 6 years ago by SmileyChris

  • Resolution set to duplicate
  • Status changed from reopened to closed

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

comment:7 Changed 4 years ago by wam

  • Resolution duplicate deleted
  • Status changed from closed to reopened
  • Version changed from SVN to 1.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 Changed 4 years ago by jonozzz

  • Cc jonozzz added

comment:9 follow-up: Changed 4 years ago by jonozzz

  • milestone set to 1.3
  • Version changed from 1.1 to 1.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 ?

comment:10 in reply to: ↑ 9 Changed 4 years ago by kmtracey

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 Changed 4 years ago by Alex

  • Component changed from Core framework to Contrib apps

Changed 3 years ago by henriquebastos

Updated patch with tests

comment:12 Changed 3 years ago by henriquebastos

  • Needs tests unset

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

comment:13 Changed 3 years ago by lukeplant

  • 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 Changed 3 years ago by gabrielhurley

  • Component changed from Contrib apps to contrib.contenttypes

comment:15 Changed 3 years ago by lrekucki

  • Type changed from defect to Bug

comment:16 Changed 3 years ago by lrekucki

  • Severity changed from normal to Normal

comment:17 Changed 3 years ago by jacob

  • milestone 1.3 deleted

Milestone 1.3 deleted

comment:11 Changed 2 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:12 Changed 2 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:13 Changed 13 months ago by aaugustin

  • Status changed from reopened to new

comment:14 Changed 8 months ago by anonymous

well i want to check if its good for my needs

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as new
The owner will be changed from adrian to anonymous. Next status will be 'assigned'
as The resolution will be set. Next status will be 'closed'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.