Ticket #3182: update_and_update_or_create.diff

File update_and_update_or_create.diff, 11.5 KB (added by Gary Wilson <gary.wilson@…>, 9 years ago)

update() from #3180 and update_or_create() together

  • tests/modeltests/update/models.py

    === added directory 'tests/modeltests/update'
    === added file 'tests/modeltests/update/__init__.py'
    === added file 'tests/modeltests/update/models.py'
     
     1"""
     234. update()
     3
     4update() will update an object's fields with the paramaters passed to it,
     5and then save the object.
     6"""
     7
     8from django.db import models
     9from django.core import validators
     10
     11class User(models.Model):
     12    username = models.CharField(maxlength=30, unique=True,
     13                                validator_list=[validators.isAlphaNumeric])
     14    first_name = models.CharField(maxlength=100)
     15    last_name = models.CharField(maxlength=100)
     16
     17    def __str__(self):
     18        return '%s %s "%s"' % (self.first_name, self.last_name, self.username)
     19
     20    class Meta:
     21        ordering = ('username',)
     22
     23__test__ = {'API_TESTS':"""
     24# Lets create a User.
     25>>> u1 = User.objects.create(username='brave', first_name='Sir', last_name='Robin')
     26
     27# Only one User in the database so far.
     28>>> User.objects.all()
     29[<User: Sir Robin "brave">]
     30
     31# Now we update the user's username and check that it was indeed updated.
     32>>> u1.update(username='notsobrave')
     33>>> u1.username
     34'notsobrave'
     35
     36# We should still only have one User in the database.
     37>>> User.objects.all()
     38[<User: Sir Robin "notsobrave">]
     39
     40# We should be able to grab the User by its new username.
     41>>> u1 = User.objects.get(username='notsobrave')
     42
     43# And we should no longer have a User with username 'brave'.
     44>>> User.objects.filter(username='brave').count()
     450L
     46
     47# Let's create another User.
     48>>> u2 = User.objects.create(username='brave', first_name='Sir', last_name='Lancelot')
     49
     50# Two Users in the database now, and we also have the first User's updated data.
     51>>> User.objects.all()
     52[<User: Sir Lancelot "brave">, <User: Sir Robin "notsobrave">]
     53
     54# We can update more than one field at a time.
     55>>> u1.update(username='pure', last_name='Galahad')
     56
     57# The user did indeed get updated.
     58>>> User.objects.all()
     59[<User: Sir Lancelot "brave">, <User: Sir Galahad "pure">]
     60
     61# If we have a dictionary of fields to change, we can pass that to
     62# update() also.
     63>>> data = {'username': 'knight', 'first_name': 'Knight'}
     64>>> u1.update(**data)
     65>>> u1
     66<User: Knight Galahad "knight">
     67>>> User.objects.all()
     68[<User: Sir Lancelot "brave">, <User: Knight Galahad "knight">]
     69"""}
  • tests/modeltests/update_or_create/models.py

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

    === modified file 'django/db/models/base.py'
     
    217217
    218218    save.alters_data = True
    219219
     220    def update(self, **kwargs):
     221        """
     222        Set the object's fields to the new values passed in as keyword
     223        arguments and then save the object.  Fields not specified in the
     224        keyword arguments will not be altered.
     225        """
     226        # Nothing to do if we have no keyword arguments.
     227        if kwargs:
     228            self.__dict__.update(kwargs)
     229            self.save()
     230
     231    update.alters_data = True
     232
    220233    def validate(self):
    221234        """
    222235        First coerces all fields on this instance to their proper Python types.
  • django/db/models/manager.py

    === modified file 'django/db/models/manager.py'
     
    6868
    6969    def get_or_create(self, **kwargs):
    7070        return self.get_query_set().get_or_create(**kwargs)
    71        
     71
     72    def update_or_create(self, **kwargs):
     73        return self.get_query_set().update_or_create(**kwargs)
     74
    7275    def create(self, **kwargs):
    7376        return self.get_query_set().create(**kwargs)
    7477
  • django/db/models/query.py

    === modified file 'django/db/models/query.py'
     
    240240            obj.save()
    241241            return obj, True
    242242
     243    def update_or_create(self, **kwargs):
     244        """
     245        Looks up an object with the given kwargs, creating one if necessary.
     246        If the object already exists, then its fields are updated with the
     247        values passed in the defaults dictionary.
     248        Returns a tuple of (object, created), where created is a boolean
     249        specifying whether an object was created.
     250        """
     251        obj, created = self.get_or_create(**kwargs)
     252        if not created:
     253            obj.update(**kwargs.pop('defaults', {}))
     254        return obj, created
     255
    243256    def latest(self, field_name=None):
    244257        """
    245258        Returns the latest object, according to the model's 'get_latest_by'
  • docs/db-api.txt

    === modified file 'docs/db-api.txt'
     
    121121Saving changes to objects
    122122=========================
    123123
    124 To save changes to an object that's already in the database, use ``save()``.
    125 
    126 Given a ``Blog`` instance ``b5`` that has already been saved to the database,
    127 this example changes its name and updates its record in the database::
    128 
    129     b5.name = 'New name'
    130     b5.save()
    131 
    132 This performs an ``UPDATE`` SQL statement behind the scenes. Django doesn't hit
     124``save()``
     125----------
     126
     127Use the ``save()`` method to save an object to the database after making
     128changes to it::
     129
     130    newblog.name = "Brave New World"
     131    newblog.save()
     132
     133This performs an ``UPDATE`` SQL statement behind the scenes (see the
     134`How Django knows to UPDATE vs. INSERT`_ section below).  Django doesn't hit
    133135the database until you explicitly call ``save()``.
    134136
    135137The ``save()`` method has no return value.
    136138
     139``update(**kwargs)``
     140--------------------
     141
     142A convenience method for updating and saving an object all in one step, where
     143(``**kwargs``) are the attributes to update.  Like ``save()``, the
     144``update()`` method has no return value.
     145
     146Using ``update()``, the above code example could be rewritten as::
     147
     148    newblog.update(name="Brave New World")
     149
     150Since ``update()`` calls ``save()`` behind the scenes, Django will hit the
     151database every time ``update()`` is called.
     152
    137153How Django knows to UPDATE vs. INSERT
    138154-------------------------------------
    139155
     
    784800
    785801.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
    786802
     803``update_or_create(**kwargs)``
     804~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     805
     806A convenience method for looking up an object with the given kwargs, and then
     807either updating the values of the object if one is found or creating an
     808object if one was not found.
     809
     810This method calls ``get_or_create()`` behind the scenes, and similarly
     811returns a tuple of ``(object, created)``, where``object`` is the updated or
     812created object and ``created`` is a boolean specifying whether a new object
     813was created.
     814
     815This is meant as a shortcut to the following type of code::
     816
     817    obj, created = Person.objects.get_or_create(first_name='John', last_name='Lennon',
     818                       defaults={'birthday': date(1940, 10, 9)})
     819    if not created:
     820            obj.update('birthday'=date(1940, 10, 9))
     821
     822This pattern gets quite unwieldy as the number of fields in a model goes up.
     823The above example can be rewritten using ``update_or_create()`` like so::
     824
     825    obj, created = Person.objects.update_or_create(first_name='John', last_name='Lennon',
     826                       defaults={'birthday': date(1940, 10, 9)})
     827
     828Any keyword arguments passed to ``update_or_create()`` will be used in a
     829call to ``get_or_create()``. If ``get_or_create()`` creates an object, then
     830nothing needs to be done by ``update_or_create()`` and a tuple of the created
     831object and ``True`` is returned. If, on the other hand, ``get_or_create()``
     832does not create a new object, then ``update_or_create()`` will update the
     833object with the values passed in the ``defaults`` parameter and a tuple of
     834the updated object and ``True`` is returned.
     835
     836The ``defaults`` parameter should be a dict of attribute-value pairs that
     837you want to update. If ``defaults`` is empty or not specified, then
     838``update_or_create()`` will act exactly like ``get_or_create()`` since there
     839would be nothing to update.
     840
     841As with ``get_or_create()``, if you need to use ``update_or_create()`` in a
     842view, please make sure to use it only in ``POST`` requests unless you have a
     843good reason not to. ``GET`` requests shouldn't have any effect on data; use
     844``POST`` whenever a request to a page has a side effect on your data. For
     845more, see `Safe methods`_ in the HTTP spec.
     846
     847.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
     848
    787849``count()``
    788850~~~~~~~~~~~
    789851
Back to Top