Opened 16 years ago

Closed 16 years ago

Last modified 13 years ago

#8318 closed (duplicate)

Unexpected behavior with ManyRelatedManager get_or_create()

Reported by: Fred Bartle Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Keywords: many related manager get_or_create
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no


I've noticed 2 things happening when using a ManyRelatedManager get_or_create method:

  1. The new related object is created but not added to the current object. Looking at django/db/models/fields/, get_or_create is not overridden() in the ManyRelatedManager definition, but create() is to add the new object.
  1. Using get_or_create() to add a new object that already exists regardless of whether or not it's linked to the current object results in a related object DoesNotExist exception.
from django.db import models

class Controller(models.Model):
    name = models.CharField(max_length=30, unique=True)

    def __unicode__(self):

class ControllerGroup(models.Model):
    name = models.CharField(max_length=30, unique=True)
    controllers = models.ManyToManyField(Controller)

    def __unicode__(self):

# create a controller
>>> c1 = Controller(name='controller1').save()

# create a controller group
>>> cg = ControllerGroup(name='my group').save()

# 'add' using get_or_create()
>>> cg.controllers.get_or_create(name='controller1')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/django/src/trunk/django/db/models/", line 84, in get_or_create
    return self.get_query_set().get_or_create(**kwargs)
  File "/usr/local/django/src/trunk/django/db/models/", line 335, in get_or_create
    return self.get(**kwargs), False
  File "/usr/local/django/src/trunk/django/db/models/", line 300, in get
    % self.model._meta.object_name)
DoesNotExist: Controller matching query does not exist.

# trying 'adding' a controller that doesn't exist
>>> cg.controllers.get_or_create(name='controller2')
(<Controller: controller2>, True)

# looks like it's been added, let's check
>>> cg.controllers.all()

Attachments (2)

8318.diff (1.9 KB ) - added by Fred Bartle 16 years ago.
override get_or_create() in ManyRelatedManager
8318.2.diff (2.3 KB ) - added by Fred Bartle 16 years ago.
fixed missing import, used correct get() method

Download all attachments as: .zip

Change History (6)

by Fred Bartle, 16 years ago

Attachment: 8318.diff added

override get_or_create() in ManyRelatedManager

comment:1 by Fred Bartle, 16 years ago

Has patch: set

Code should actually read:

# create a controller
>>> c1 = Controller(name='controller1')

# create a controller group
>>> cg = ControllerGroup(name='my group')

comment:2 by Fred Bartle, 16 years ago

Patch needs improvement: set

My patch is not correct, I will spend some time reviewing it.

by Fred Bartle, 16 years ago

Attachment: 8318.2.diff added

fixed missing import, used correct get() method

comment:3 by Alex Gaynor, 16 years ago

Resolution: duplicate
Status: newclosed

I believe this is a dupe of #3121(which was fixed in r8415), if this is incorrect, please reopen.

comment:4 by Jacob, 13 years ago

milestone: 1.0

Milestone 1.0 deleted

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