Ticket #3182: 3182-update_or_create-r9844.diff

File 3182-update_or_create-r9844.diff, 12.1 KB (added by mrmachine, 6 years ago)

Updated to work with r9844.

  • django/db/models/base.py

     
    329329
    330330    save.alters_data = True
    331331
     332    def update(self, **kwargs):
     333        """
     334        Set the object's fields to the new values passed in as keyword
     335        arguments and then save the object.  Fields not specified in the
     336        keyword arguments will not be altered.
     337        """
     338        for k, v in kwargs.items():
     339            setattr(self, k, v)
     340            self.save()
     341
     342    update.alters_data = True
     343
    332344    def save_base(self, raw=False, cls=None, force_insert=False,
    333345            force_update=False):
    334346        """
  • django/db/models/manager.py

     
    9595    def get_or_create(self, **kwargs):
    9696        return self.get_query_set().get_or_create(**kwargs)
    9797
     98    def update_or_create(self, **kwargs):
     99        return self.get_query_set().update_or_create(**kwargs)
     100
    98101    def create(self, **kwargs):
    99102        return self.get_query_set().create(**kwargs)
    100103
  • django/db/models/query.py

     
    379379                except self.model.DoesNotExist:
    380380                    raise e
    381381
     382    def update_or_create(self, **kwargs):
     383        """
     384        Looks up an object with the given kwargs, creating one if necessary.
     385        If the object already exists, then its fields are updated with the
     386        values passed in the defaults dictionary.
     387        Returns a tuple of (object, created), where created is a boolean
     388        specifying whether an object was created.
     389        """
     390        obj, created = self.get_or_create(**kwargs)
     391        if not created:
     392            obj.update(**kwargs.pop('defaults', {}))
     393        return obj, created
     394
    382395    def latest(self, field_name=None):
    383396        """
    384397        Returns the latest object, according to the model's 'get_latest_by'
  • tests/modeltests/update_or_create/models.py

     
     1"""
     2update_or_create() tries to look up an object with the given parameters.
     3If an object is found, it updates the object.  If an object isn't found, it
     4creates one with the given parameters.
     5"""
     6
     7from django.db import models
     8
     9class Person(models.Model):
     10    first_name = models.CharField(max_length=100)
     11    last_name = models.CharField(max_length=100)
     12    birthday = models.DateField()
     13
     14    def __str__(self):
     15        return '%s %s, Birthday: %s' % (self.first_name, self.last_name,
     16                                        self.birthday)
     17
     18    class Meta:
     19        ordering = ('last_name',)
     20
     21__test__ = {'API_TESTS': """
     22# Create a Person.
     23>>> from datetime import date
     24>>> p = Person.objects.create(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
     25
     26# Only one Person is in the database at this point.
     27>>> Person.objects.all()
     28[<Person: John Lennon, Birthday: 1940-10-09>]
     29
     30# update_or_create() a Person with the same name.
     31>>> p, created = Person.objects.update_or_create(first_name='John', last_name='Lennon', defaults={'birthday': date(1970, 10, 9)})
     32
     33# update_or_create() didn't have to create an object.
     34>>> created
     35False
     36
     37# There's still only one Person in the database, and their birthday was updated.
     38>>> Person.objects.all()
     39[<Person: John Lennon, Birthday: 1970-10-09>]
     40
     41# update_or_create() a Person with a different name.
     42>>> p, created = Person.objects.update_or_create(first_name='George', last_name='Harrison', defaults={'birthday': date(1943, 2, 25)})
     43>>> created
     44True
     45
     46# Two People in the database now.
     47>>> Person.objects.all()
     48[<Person: George Harrison, Birthday: 1943-02-25>, <Person: John Lennon, Birthday: 1970-10-09>]
     49
     50# If we execute the exact same statement, it won't create a Person.
     51>>> p, created = Person.objects.update_or_create(first_name='George', last_name='Harrison', defaults={'birthday': date(1943, 2, 25)})
     52>>> created
     53False
     54
     55# The two People in the database haven't changed.
     56>>> Person.objects.all()
     57[<Person: George Harrison, Birthday: 1943-02-25>, <Person: John Lennon, Birthday: 1970-10-09>]
     58
     59# update_or_create() can take an empty 'defaults' parameter, but in this
     60# situation behaves exactly like get_or_create().  This is useful if you are
     61# building the 'defaults' dictionary dynamically.
     62>>> p, created = Person.objects.update_or_create(first_name='George', last_name='Harrison', defaults={})
     63>>> created
     64False
     65
     66# A different name with an empty 'defaults'.
     67>>> p, created = Person.objects.update_or_create(first_name='John', last_name='Smith', birthday=date(1950, 2, 10), defaults={})
     68>>> created
     69True
     70
     71>>> Person.objects.all()
     72[<Person: George Harrison, Birthday: 1943-02-25>, <Person: John Lennon, Birthday: 1970-10-09>, <Person: John Smith, Birthday: 1950-02-10>]
     73"""}
  • tests/modeltests/update/models.py

     
    11"""
    2 Tests for the update() queryset method that allows in-place, multi-object
    3 updates.
     2Tests for the update() queryset and model methods that allow in-place updates to multiple
     3objects or a single object.
    44"""
    55
    66from django.db import models
     
    2222
    2323
    2424__test__ = {'API_TESTS': """
     25# QuerySet method ################################################################
     26
    2527>>> DataPoint(name="d0", value="apple").save()
    2628>>> DataPoint(name="d2", value="banana").save()
    2729>>> d3 = DataPoint.objects.create(name="d3", value="banana")
    2830>>> RelatedPoint(name="r1", data=d3).save()
    2931
    3032Objects are updated by first filtering the candidates into a queryset and then
    31 calling the update() method. It executes immediately and returns nothing.
     33calling the update() method. It executes immediately and returns the number of
     34objects affected.
    3235
    3336>>> DataPoint.objects.filter(value="apple").update(name="d1")
    34371
     
    7477    ...
    7578AssertionError: Cannot update a query once a slice has been taken.
    7679
     80# Model method ################################################################
     81
     82# Get an existing DataPoint object.
     83>>> d = DataPoint.objects.get(name="d2")
     84>>> d.value, d.another_value
     85(u'thing', u'peaches')
     86
     87# Update multiple fields.
     88>>> d.update(value='oranges', another_value='apples')
     89
     90# Check that the object was updated.
     91>>> d.value, d.another_value
     92('oranges', 'apples')
     93
     94# Check that the object was saved.
     95>>> d = DataPoint.objects.get(name="d2", value="oranges", another_value="apples")
     96>>> d.value, d.another_value
     97(u'oranges', u'apples')
     98
     99# Get an existing RelatedPoint object.
     100>>> r = RelatedPoint.objects.get(name="r1")
     101>>> r.data
     102<DataPoint: d1>
     103
     104# Update the ForeignKey field.
     105>>> r.update(data=d)
     106>>> r.data
     107<DataPoint: d2>
     108
     109# Check that the object was saved.
     110>>> RelatedPoint.objects.get(name="r1").data
     111<DataPoint: d2>
     112
     113# You can also update an object that has not yet been saved.
     114>>> d = DataPoint(name="d4", value="planes", another_value="trains")
     115>>> d.update(another_value="automobiles")
     116>>> d.value, d.another_value
     117('planes', 'automobiles')
    77118"""
    78119}
  • docs/ref/models/querysets.txt

     
    896896
    897897.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
    898898
     899``update_or_create(**kwargs)``
     900~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     901
     902A convenience method for looking up an object with the given kwargs, and then
     903either updating the values of the object if one is found or creating an
     904object if one was not found.
     905
     906This method calls ``get_or_create()`` behind the scenes, and similarly
     907returns a tuple of ``(object, created)``, where``object`` is the updated or
     908created object and ``created`` is a boolean specifying whether a new object
     909was created.
     910
     911This is meant as a shortcut to the following type of code::
     912
     913    obj, created = Person.objects.get_or_create(first_name='John', last_name='Lennon',
     914                       defaults={'birthday': date(1940, 10, 9)})
     915    if not created:
     916            obj.update(birthday=date(1940, 10, 9))
     917
     918This pattern gets quite unwieldy as the number of fields in a model goes up.
     919The above example can be rewritten using ``update_or_create()`` like so::
     920
     921    obj, created = Person.objects.update_or_create(first_name='John', last_name='Lennon',
     922                       defaults={'birthday': date(1940, 10, 9)})
     923
     924Any keyword arguments passed to ``update_or_create()`` will be used in a
     925call to ``get_or_create()``. If ``get_or_create()`` creates an object, then
     926nothing needs to be done by ``update_or_create()`` and a tuple of the created
     927object and ``True`` is returned. If, on the other hand, ``get_or_create()``
     928does not create a new object, then ``update_or_create()`` will update the
     929object with the values passed in the ``defaults`` parameter and a tuple of
     930the updated object and ``True`` is returned.
     931
     932The ``defaults`` parameter should be a dict of attribute-value pairs that
     933you want to update. If ``defaults`` is empty or not specified, then
     934``update_or_create()`` will act exactly like ``get_or_create()`` since there
     935would be nothing to update.
     936
     937As with ``get_or_create()``, if you need to use ``update_or_create()`` in a
     938view, please make sure to use it only in ``POST`` requests unless you have a
     939good reason not to. ``GET`` requests shouldn't have any effect on data; use
     940``POST`` whenever a request to a page has a side effect on your data. For
     941more, see `Safe methods`_ in the HTTP spec.
     942
     943.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
     944
    899945``count()``
    900946~~~~~~~~~~~
    901947
  • docs/ref/models/instances.txt

     
    4949your object the first time you call ``save()``::
    5050
    5151    >>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
    52     >>> b2.id     # Returns None, because b doesn't have an ID yet.
     52    >>> b2.id     # Returns None, because b2 doesn't have an ID yet.
    5353    >>> b2.save()
    5454    >>> b2.id     # Returns the ID of your new object.
    5555
     
    9494Given the above ``'Cheddar Talk'`` blog example, this example would override the
    9595previous record in the database::
    9696
    97     b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
    98     b4.save()  # Overrides the previous blog with ID=3!
     97    >>> b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
     98    >>> b4.save()  # Overrides the previous blog with ID=3!
    9999
    100100See `How Django knows to UPDATE vs. INSERT`_, below, for the reason this
    101101happens.
     
    187187errors that are difficult to track down. This feature is for advanced use
    188188only.
    189189
     190.. _ref-models-update:
     191
     192Updating an existing model instance
     193~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     194
     195.. versionadded:: 1.1
     196
     197To upate and save a model instance in one step, call ``update()``:
     198
     199.. method:: Model.update(**kwargs)
     200
     201A convenience method for updating and saving a model instance in one step,
     202where (``**kwargs``) are the attributes to update.  Like ``save()``, the
     203``update()`` method has no return value.
     204
     205Given the earlier ``'Not Cheddar'`` blog example, this example would update
     206and save the existing model instance::
     207
     208    >>> b4.update(name='All Cheddar', tagline='Nothing but cheddar cheese')
     209
     210Since ``update()`` calls ``save()`` behind the scenes, Django will hit the
     211database every time ``update()`` is called.
     212
    190213.. _model-instance-methods:
    191214
    192215Other model instance methods
Back to Top