Code

Ticket #3182: update_and_update_or_create.diff

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

update() from #3180 and update_or_create() together

Line 
1=== added directory 'tests/modeltests/update'
2=== added file 'tests/modeltests/update/__init__.py'
3=== added file 'tests/modeltests/update/models.py'
4--- tests/modeltests/update/models.py   1970-01-01 00:00:00 +0000
5+++ tests/modeltests/update/models.py   2006-12-22 06:05:43 +0000
6@@ -0,0 +1,69 @@
7+"""
8+34. update()
9+
10+update() will update an object's fields with the paramaters passed to it,
11+and then save the object.
12+"""
13+
14+from django.db import models
15+from django.core import validators
16+
17+class User(models.Model):
18+    username = models.CharField(maxlength=30, unique=True,
19+                                validator_list=[validators.isAlphaNumeric])
20+    first_name = models.CharField(maxlength=100)
21+    last_name = models.CharField(maxlength=100)
22+
23+    def __str__(self):
24+        return '%s %s "%s"' % (self.first_name, self.last_name, self.username)
25+
26+    class Meta:
27+        ordering = ('username',)
28+
29+__test__ = {'API_TESTS':"""
30+# Lets create a User.
31+>>> u1 = User.objects.create(username='brave', first_name='Sir', last_name='Robin')
32+
33+# Only one User in the database so far.
34+>>> User.objects.all()
35+[<User: Sir Robin "brave">]
36+
37+# Now we update the user's username and check that it was indeed updated.
38+>>> u1.update(username='notsobrave')
39+>>> u1.username
40+'notsobrave'
41+
42+# We should still only have one User in the database.
43+>>> User.objects.all()
44+[<User: Sir Robin "notsobrave">]
45+
46+# We should be able to grab the User by its new username.
47+>>> u1 = User.objects.get(username='notsobrave')
48+
49+# And we should no longer have a User with username 'brave'.
50+>>> User.objects.filter(username='brave').count()
51+0L
52+
53+# Let's create another User.
54+>>> u2 = User.objects.create(username='brave', first_name='Sir', last_name='Lancelot')
55+
56+# Two Users in the database now, and we also have the first User's updated data.
57+>>> User.objects.all()
58+[<User: Sir Lancelot "brave">, <User: Sir Robin "notsobrave">]
59+
60+# We can update more than one field at a time.
61+>>> u1.update(username='pure', last_name='Galahad')
62+
63+# The user did indeed get updated.
64+>>> User.objects.all()
65+[<User: Sir Lancelot "brave">, <User: Sir Galahad "pure">]
66+
67+# If we have a dictionary of fields to change, we can pass that to
68+# update() also.
69+>>> data = {'username': 'knight', 'first_name': 'Knight'}
70+>>> u1.update(**data)
71+>>> u1
72+<User: Knight Galahad "knight">
73+>>> User.objects.all()
74+[<User: Sir Lancelot "brave">, <User: Knight Galahad "knight">]
75+"""}
76
77=== added directory 'tests/modeltests/update_or_create'
78=== added file 'tests/modeltests/update_or_create/__init__.py'
79=== added file 'tests/modeltests/update_or_create/models.py'
80--- tests/modeltests/update_or_create/models.py 1970-01-01 00:00:00 +0000
81+++ tests/modeltests/update_or_create/models.py 2006-12-24 22:33:57 +0000
82@@ -0,0 +1,75 @@
83+"""
84+35. update_or_create()
85+
86+update_or_create() tries to look up an object with the given parameters.
87+If an object is found, it updates the object.  If an object isn't found, it
88+creates one with the given parameters.
89+"""
90+
91+from django.db import models
92+
93+class Person(models.Model):
94+    first_name = models.CharField(maxlength=100)
95+    last_name = models.CharField(maxlength=100)
96+    birthday = models.DateField()
97+
98+    def __str__(self):
99+        return '%s %s, Birthday: %s' % (self.first_name, self.last_name,
100+                                        self.birthday)
101+
102+    class Meta:
103+        ordering = ('last_name',)
104+
105+__test__ = {'API_TESTS':"""
106+# Create a Person.
107+>>> from datetime import date
108+>>> p = Person.objects.create(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
109+
110+# Only one Person is in the database at this point.
111+>>> Person.objects.all()
112+[<Person: John Lennon, Birthday: 1940-10-09>]
113+
114+# update_or_create() a Person with the same name.
115+>>> p, created = Person.objects.update_or_create(first_name='John', last_name='Lennon', defaults={'birthday': date(1970, 10, 9)})
116+
117+# update_or_create() didn't have to create an object.
118+>>> created
119+False
120+
121+# There's still only one Person in the database, and their birthday was updated.
122+>>> Person.objects.all()
123+[<Person: John Lennon, Birthday: 1970-10-09>]
124+
125+# update_or_create() a Person with a different name.
126+>>> p, created = Person.objects.update_or_create(first_name='George', last_name='Harrison', defaults={'birthday': date(1943, 2, 25)})
127+>>> created
128+True
129+
130+# Two People in the database now.
131+>>> Person.objects.all()
132+[<Person: George Harrison, Birthday: 1943-02-25>, <Person: John Lennon, Birthday: 1970-10-09>]
133+
134+# If we execute the exact same statement, it won't create a Person.
135+>>> p, created = Person.objects.update_or_create(first_name='George', last_name='Harrison', defaults={'birthday': date(1943, 2, 25)})
136+>>> created
137+False
138+
139+# The two People in the database haven't changed.
140+>>> Person.objects.all()
141+[<Person: George Harrison, Birthday: 1943-02-25>, <Person: John Lennon, Birthday: 1970-10-09>]
142+
143+# update_or_create() can take an empty 'defaults' parameter, but in this
144+# situation behaves exactly like get_or_create().  This is useful if you are
145+# building the 'defaults' dictionary dynamically.
146+>>> p, created = Person.objects.update_or_create(first_name='George', last_name='Harrison', defaults={})
147+>>> created
148+False
149+
150+# A different name with an empty 'defaults'.
151+>>> p, created = Person.objects.update_or_create(first_name='John', last_name='Smith', birthday=date(1950, 2, 10), defaults={})
152+>>> created
153+True
154+
155+>>> Person.objects.all()
156+[<Person: George Harrison, Birthday: 1943-02-25>, <Person: John Lennon, Birthday: 1970-10-09>, <Person: John Smith, Birthday: 1950-02-10>]
157+"""}
158
159=== modified file 'django/db/models/base.py'
160--- django/db/models/base.py    2006-12-19 04:35:09 +0000
161+++ django/db/models/base.py    2006-12-22 06:05:43 +0000
162@@ -217,6 +217,19 @@
163 
164     save.alters_data = True
165 
166+    def update(self, **kwargs):
167+        """
168+        Set the object's fields to the new values passed in as keyword
169+        arguments and then save the object.  Fields not specified in the
170+        keyword arguments will not be altered.
171+        """
172+        # Nothing to do if we have no keyword arguments.
173+        if kwargs:
174+            self.__dict__.update(kwargs)
175+            self.save()
176+
177+    update.alters_data = True
178+
179     def validate(self):
180         """
181         First coerces all fields on this instance to their proper Python types.
182
183=== modified file 'django/db/models/manager.py'
184--- django/db/models/manager.py 2006-12-19 04:35:09 +0000
185+++ django/db/models/manager.py 2006-12-22 06:44:11 +0000
186@@ -68,7 +68,10 @@
187 
188     def get_or_create(self, **kwargs):
189         return self.get_query_set().get_or_create(**kwargs)
190-       
191+
192+    def update_or_create(self, **kwargs):
193+        return self.get_query_set().update_or_create(**kwargs)
194+
195     def create(self, **kwargs):
196         return self.get_query_set().create(**kwargs)
197 
198
199=== modified file 'django/db/models/query.py'
200--- django/db/models/query.py   2006-12-19 04:35:09 +0000
201+++ django/db/models/query.py   2006-12-24 22:15:33 +0000
202@@ -240,6 +240,19 @@
203             obj.save()
204             return obj, True
205 
206+    def update_or_create(self, **kwargs):
207+        """
208+        Looks up an object with the given kwargs, creating one if necessary.
209+        If the object already exists, then its fields are updated with the
210+        values passed in the defaults dictionary.
211+        Returns a tuple of (object, created), where created is a boolean
212+        specifying whether an object was created.
213+        """
214+        obj, created = self.get_or_create(**kwargs)
215+        if not created:
216+            obj.update(**kwargs.pop('defaults', {}))
217+        return obj, created
218+
219     def latest(self, field_name=None):
220         """
221         Returns the latest object, according to the model's 'get_latest_by'
222
223=== modified file 'docs/db-api.txt'
224--- docs/db-api.txt     2006-12-19 04:35:09 +0000
225+++ docs/db-api.txt     2006-12-26 06:04:05 +0000
226@@ -121,19 +121,35 @@
227 Saving changes to objects
228 =========================
229 
230-To save changes to an object that's already in the database, use ``save()``.
231-
232-Given a ``Blog`` instance ``b5`` that has already been saved to the database,
233-this example changes its name and updates its record in the database::
234-
235-    b5.name = 'New name'
236-    b5.save()
237-
238-This performs an ``UPDATE`` SQL statement behind the scenes. Django doesn't hit
239+``save()``
240+----------
241+
242+Use the ``save()`` method to save an object to the database after making
243+changes to it::
244+
245+    newblog.name = "Brave New World"
246+    newblog.save()
247+
248+This performs an ``UPDATE`` SQL statement behind the scenes (see the
249+`How Django knows to UPDATE vs. INSERT`_ section below).  Django doesn't hit
250 the database until you explicitly call ``save()``.
251 
252 The ``save()`` method has no return value.
253 
254+``update(**kwargs)``
255+--------------------
256+
257+A convenience method for updating and saving an object all in one step, where
258+(``**kwargs``) are the attributes to update.  Like ``save()``, the
259+``update()`` method has no return value.
260+
261+Using ``update()``, the above code example could be rewritten as::
262+
263+    newblog.update(name="Brave New World")
264+
265+Since ``update()`` calls ``save()`` behind the scenes, Django will hit the
266+database every time ``update()`` is called.
267+
268 How Django knows to UPDATE vs. INSERT
269 -------------------------------------
270 
271@@ -784,6 +800,52 @@
272 
273 .. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
274 
275+``update_or_create(**kwargs)``
276+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
277+
278+A convenience method for looking up an object with the given kwargs, and then
279+either updating the values of the object if one is found or creating an
280+object if one was not found.
281+
282+This method calls ``get_or_create()`` behind the scenes, and similarly
283+returns a tuple of ``(object, created)``, where``object`` is the updated or
284+created object and ``created`` is a boolean specifying whether a new object
285+was created.
286+
287+This is meant as a shortcut to the following type of code::
288+
289+    obj, created = Person.objects.get_or_create(first_name='John', last_name='Lennon',
290+                       defaults={'birthday': date(1940, 10, 9)})
291+    if not created:
292+           obj.update('birthday'=date(1940, 10, 9))
293+
294+This pattern gets quite unwieldy as the number of fields in a model goes up.
295+The above example can be rewritten using ``update_or_create()`` like so::
296+
297+    obj, created = Person.objects.update_or_create(first_name='John', last_name='Lennon',
298+                       defaults={'birthday': date(1940, 10, 9)})
299+
300+Any keyword arguments passed to ``update_or_create()`` will be used in a
301+call to ``get_or_create()``. If ``get_or_create()`` creates an object, then
302+nothing needs to be done by ``update_or_create()`` and a tuple of the created
303+object and ``True`` is returned. If, on the other hand, ``get_or_create()``
304+does not create a new object, then ``update_or_create()`` will update the
305+object with the values passed in the ``defaults`` parameter and a tuple of
306+the updated object and ``True`` is returned.
307+
308+The ``defaults`` parameter should be a dict of attribute-value pairs that
309+you want to update. If ``defaults`` is empty or not specified, then
310+``update_or_create()`` will act exactly like ``get_or_create()`` since there
311+would be nothing to update.
312+
313+As with ``get_or_create()``, if you need to use ``update_or_create()`` in a
314+view, please make sure to use it only in ``POST`` requests unless you have a
315+good reason not to. ``GET`` requests shouldn't have any effect on data; use
316+``POST`` whenever a request to a page has a side effect on your data. For
317+more, see `Safe methods`_ in the HTTP spec.
318+
319+.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
320+
321 ``count()``
322 ~~~~~~~~~~~
323 
324