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

3

6

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)
Clean answered 10/9, 2019 at 5:58 Comment(3)
post the model and the form tooBidle
Read the docs on objects.create: docs.djangoproject.com/en/2.2/ref/models/querysets/#create It only takes keyword arguments in the form of model_prop=value and no positional arguments. The ** operator in python applies the dictionary as keyword arguments to the function. See #37401.Alright
If your RawProductCreateForm is a ModelForm, you could use the save method to create the Product object e.g. my_form.save()Haul
H
11

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.

Heterosexuality answered 10/9, 2019 at 6:4 Comment(0)
A
4

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']
Ambidextrous answered 10/9, 2019 at 6:11 Comment(2)
so passing the cleaned_data with ** tells the function to treat cleaned_data as kwarg right ?Clean
Correct. In simpler words it converts dictionary to named argumentsAmbidextrous
M
0

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>)
Mellifluous answered 10/9, 2019 at 6:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.