11

How do I pass an argument to my custom save method, preserving proper *args, **kwargs for passing to te super method? I was trying something like:

form.save(my_value)

and

def save(self, my_value=None, *args, **kwargs):

   super(MyModel, self).save(*args, **kwargs)

   print my_value

But this doesn't seem to work. What am I doing wrong?

Edit: I found this example (see the last message, for passing 'reorder'): http://groups.google.com/group/django-users/browse_thread/thread/b285698ea3cabfc9/6ce8a4517875cb40?lnk=raot

This is essentially what I am trying to do, but my_value is said to be an unexpected argument for some reason.

Gabriel Ilharco
  • 1,649
  • 1
  • 21
  • 34
Nikita
  • 769
  • 2
  • 8
  • 18
  • You're unrolling the arguments in the call to save! – Humphrey Bogart Mar 29 '10 at 02:16
  • Defined method `save(self, my_value=None, *args, **kwargs)` expects keyword argument: `save(my_value=some_value)` (check this question about [positional and keyword arguments](https://stackoverflow.com/questions/9450656/positional-argument-v-s-keyword-argument/57819001#57819001)) – Denis Jul 11 '21 at 09:22

3 Answers3

26

Keyword arguments must follow the positional arguments. Try this instead:

def save(self, my_value, *args, **kwargs):
    ....

or:

def save(self, *args, **kwargs):
    my_value = kwargs.pop('my_value', None)
Daniel Naab
  • 22,690
  • 8
  • 54
  • 55
5

You can try the following.

Override the save method as:

def save(self, my_val, *args, **kwargs):
    print my_val
    # do_something here
    return super(MyModel, self).save(*args, **kwargs)

On calling the save method as:

MyModel.save(my_val="fooooo")

this will print my_val and save it.

ImportError
  • 358
  • 5
  • 17
ashish singh
  • 146
  • 2
  • 2
3

The existing answers are incomplete.

The problem with Model.save is that there are multiple ways to get to it, most notably through Model.objects.create(). A queryset create() call will not pass additional arguments to Model.save and your code might not behave as expected.

You can easily see the source code for create() and other methods (get_or_create, update_or_create) here: https://github.com/django/django/blob/2.2.7/django/db/models/query.py#L415

The bulk_create method of QuerySet does not call save at all. Which means any custom logic will be entirely ignored.

Because of these risks I would consider the premise of the question an anti-pattern to be avoided. Rather than overloading the built in save method, create an entirely different (factory) method to encompass your special behavior e.g. mymodel.special_save().

mastaBlasta
  • 5,700
  • 1
  • 24
  • 26