Ticket #16865: patch_16865_get_or_create_move_for_write-3.diff

File patch_16865_get_or_create_move_for_write-3.diff, 2.8 KB (added by trbs, 3 years ago)
  • django/db/models/query.py

    diff --git a/django/db/models/query.py b/django/db/models/query.py
    index 8bf08b7..441426a 100644
    a b class QuerySet(object): 
    455455            if f.attname in lookup:
    456456                lookup[f.name] = lookup.pop(f.attname)
    457457        try:
    458             self._for_write = True
    459458            return self.get(**lookup), False
    460459        except self.model.DoesNotExist:
     460            self._for_write = True
    461461            try:
    462462                params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
    463463                params.update(defaults)
  • docs/ref/models/querysets.txt

    diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
    index 8ec7cfc..fbf4882 100644
    a b data-import scripts. For example:: 
    13181318        obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    13191319        obj.save()
    13201320
     1321.. note::
     1322    When using multiple databases with some type of master-slave router ``get_or_create()``
     1323    will potentially use a slave for the initial lookup. If there is a lot of replication
     1324    lag the object might exist on the master but is not yet propagated to the slave. In
     1325    this case creating the object will fail and the existing object will be fetched from
     1326    the master database.
     1327
     1328    Changed in Django 1.5: In Django versions before 1.5 the master database was always
     1329    used and ``get_or_create()`` was not able to use the slaves.
     1330
    13211331This pattern gets quite unwieldy as the number of fields in a model goes up.
    13221332The above example can be rewritten using ``get_or_create()`` like so::
    13231333
  • tests/modeltests/get_or_create/tests.py

    diff --git a/tests/modeltests/get_or_create/tests.py b/tests/modeltests/get_or_create/tests.py
    index 1e300fb..ce9169a 100644
    a b class GetOrCreateTests(TestCase): 
    6464            formatted_traceback = traceback.format_exc()
    6565            self.assertIn('obj.save', formatted_traceback)
    6666
     67        # get_or_create should only set _for_write when it's actually doing a
     68        # create action. This makes sure that the initial .get() will be able
     69        # to use a slave database. Specially when some form of database pinning
     70        # is in place this will help to not put all the SELECT queries on the master.
     71        # See #16865
     72        qs = Person.objects.get_query_set()
     73        p, created = qs.get_or_create(first_name="John", last_name="Lennon")
     74        self.assertFalse(created)
     75        self.assertFalse(qs._for_write)
     76
     77        p, created = qs.get_or_create(
     78            first_name="Stuart", last_name="Sutcliffe", defaults={
     79                'birthday': date(1940, 6, 23)
     80            }
     81        )
     82        self.assertTrue(created)
     83        self.assertTrue(qs._for_write)
     84
Back to Top