Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#29733 closed Cleanup/optimization (invalid)

update_or_create - documentation misleading

Reported by: David Pratten Owned by: nobody
Component: Documentation Version: 2.1
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When update_or_create searches the table for a record to update it searches all fields marked 'unique' or 'primary_key'.

In the case where a record has two candidate keys the update_or_create function will fail to update either the primary key or the candidate key, leading to an Integrity Error.

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update-or-create

This behavour is not 'wrong'. But it is surprising and a time waster.

class Coa(models.Model):
    def __str__(self):
        return f'{self.qbac}'
    trantype = models.CharField(max_length=255, db_column=u'TranType', blank=True) 
    qbac = models.CharField( unique=True, max_length=255, db_column=u'QBAc') 
    guid = models.CharField(max_length=32, primary_key=True)
    account_type=models.CharField(max_length=20)

Containing the following record:

"ACCNT", "Advantage Saver", "c6f30c15c9dd1e5af9143fd7bed99315", "A"

The following, otherwise sensible, code fails with an IntegrityError

obj, created = Coa.objects.update_or_create(guid='c6f30c15c9dd1e5af9143fd7bed99315',
defaults={'trantype': 'ACCNT', 'qbac': 'A', 'account_type': 'A' },)

because the search is on both guid AND qbac rather than just on guid as requested by the single field in the **kwargs.

Recommend clarification in the docu that it is not possible to search only on one field if there are multiple unique constraints in the model.

David

Change History (2)

comment:1 by Alexander Holmbäck, 6 years ago

Hi David,

I can't replicate this behavior and the update works as expected. Make sure that there isn't another record where the value of qbac is set to 'A' (in case an IntegrityError is rightfully raised), if the problem persist, please provide the message and stacktrace of your error so that I can test this further.

comment:2 by Carlton Gibson, 6 years ago

Resolution: invalid
Status: newclosed

Adding the following to the UpdateOrCreateTests (in `get_or_create` module) does not produce a failure:

    def test_29733(self):
        p = Person.objects.create(
            first_name='John', last_name='Lennon', birthday=date(1940, 10, 9)
        )
        p, created = Person.objects.update_or_create(
            pk=p.pk, defaults={
                'first_name':'John',
            }
        )
        self.assertFalse(created)

The Person model is unique on the primary key and first_name fields.
(So AFAICS it should be a test case for your example.)

As such I'm going to close this as invalid. If you can provide a failing test case I'm happy to re-open.

Last edited 6 years ago by Carlton Gibson (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top