Any insight into the reasoning behind this design decision? It seems to me that having obj.save()
return something, has only benefits (like method chaining) and no drawbacks.

- 6,270
- 9
- 40
- 53
3 Answers
It's generally considered good practice in Python to have functions that primarily affect existing objects not return themselves. For instance, sorted(yourlist)
returns a sorted list but yourlist.sort()
sorts the list in-place and does not return anything.
Performing multiple operations with side-effects (as opposed to no-side-effect functions where the focus is on the return value) on a single line is not really good practice. The code will be more compact in terms of number of lines, but it will be harder to read because important side-effects may be buried in the middle of a chain. If you want to use method chaining, use functions with no side effects in the beginning of the chain and then have a single function with a side effect like .save()
at the end.
To put it another way, in a method chain, the beginning of the chain is the input, the middle of the chain transforms the input (navigating down a tree, sorting the input, changing case of a string etc) and the end of the chain is the functional part that does work with side-effects. If you bury methods with side-effects in the middle of the chain then it will be unclear what your method chain actually does.

- 48,506
- 64
- 207
- 283

- 19,595
- 7
- 57
- 73
-
actualy save() returns the saved object , maybe it is new on django 1.5 ? – maazza Apr 17 '13 at 10:38
-
3@maazza I just tried this on Django 1.5.1 and save() still returns None. [The source code for the latest dev version](https://github.com/django/django/blob/master/django/db/models/base.py#L492) also doesn't appear to return anything. – Andrew Gorcester Apr 17 '13 at 17:12
-
true , i used a modelform http://stackoverflow.com/questions/7428245/model-form-save-get-the-saved-object – maazza Apr 17 '13 at 19:35
-
1@maazza Oh, I see. I feel that is a different case in that you are calling .save() on a form and it is returning a different object, not itself. FWIW I think it would be cleaner if ModelForm did not have a .save() and instead had a method to instantiate an object in memory without side-effects, just like User() instantiates a User object. Then you can call .save() on that. But that is just my personal opinion, and there may be other issues I haven't considered that preclude doing that. – Andrew Gorcester Apr 17 '13 at 20:06
-
This answer is probably best, but if you want to return an object, just use `.save(commit=False)`. https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method – trpt4him Dec 12 '14 at 21:32
This reminds me of the general principle that Greg Ward espoused at Pycon2015 recently, not to confuse functions with procedures. Every function should return a value or have a side-effect, but not both.
Basically the same question is asked of dict.update().

- 1
- 1

- 7,975
- 4
- 58
- 71
Since this is the first result that I get when searching for "django return saved object", to compliment Andrew's answer, if you still want to return the saved object, instead of using:
ExampleModel(title=title).save()
which returns None, you'd use:
saved_instance = ExampleModel.objects.create(title=title)
And this works because ExampleModel.objects
is a Model Manager rather than an instance of the class, so it's not returning itself.

- 149
- 1
- 3