Opened 7 years ago

Closed 7 years ago

Last modified 4 years ago

#8318 closed (duplicate)

Unexpected behavior with ManyRelatedManager get_or_create()

Reported by: fredbartle Owned by: nobody
Component: Database layer (models, ORM) Version: master
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: UI/UX:


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 fredbartle 7 years ago.
override get_or_create() in ManyRelatedManager
8318.2.diff (2.3 KB) - added by fredbartle 7 years ago.
fixed missing import, used correct get() method

Download all attachments as: .zip

Change History (6)

Changed 7 years ago by fredbartle

override get_or_create() in ManyRelatedManager

comment:1 Changed 7 years ago by fredbartle

  • Has patch set
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Code should actually read:

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

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

comment:2 Changed 7 years ago by fredbartle

  • Patch needs improvement set

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

Changed 7 years ago by fredbartle

fixed missing import, used correct get() method

comment:3 Changed 7 years ago by Alex

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

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

comment:4 Changed 4 years ago by jacob

  • milestone 1.0 deleted

Milestone 1.0 deleted

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