create() takes 1 positional argument but 2 were given? Django

11.8k Views Asked by At

I was confused to why when I run this code it returns an error

create() takes 1 positional argument but 2 were given

if request.method == "POST":
my_form = RawProductCreateForm(request.POST)
if my_form.is_valid():
    Product.objects.create(my_form.cleaned_data)

but when I modify on the create method and add ** before passing the cleaned data it works!

Product.objects.create(**my_form.cleaned_data)
3

There are 3 best solutions below

0
On

It is because create takes keyword arguments, like

    Product.objects.create(product_name="Dish Soap", product_price=73)

Placing the ** before it tells the model to treat my_form.cleaned_data as a dictionary of keyword arguments.

2
On

The create function under the hood looks more less like this:

def create(self, **data):
   pass

As you can see you have one positional argument self, other one is just a key words dictionary. When you call this function like this:

Product.objects.create(my_form.cleaned_data)

You are passing two positional arguments one is objects this is how python handle classes and methods and other one is my_form.cleaned_data, but the function exptes only one positional and any numbers of named arguments. In second call:

Product.objects.create(**my_form.cleaned_data)

lets say the my_form.cleaned_data looks like this:

{ 
  'age': 1,
  'name': 'good product'
}

so the equvialent of the second call would be

Product.objects.create(name='good product', age=1)

As you can see you have only one positional argument objects and 2 named arguments. In create function you can refer to data like this:

def create(self, **data):
   name = data['name']
   age = data['age']
0
On

This happens when you try to insert data without a point to the field defined in the model. To fix this you have to pass field name inside the create() with assignment operator.

Product.objects.create(field1="<field 1 data>", field2=<field2 data>)