Reputation: 6319
I'm trying to use get_or_create()
for some fields in my forms, but I'm getting a 500 error when I try to do so.
One of the lines looks like this:
customer.source = Source.objects.get_or_create(name="Website")
The error I get for the above code is:
Cannot assign "(<Source: Website>, False)": "Customer.source" must be a "Source" instance.
Upvotes: 327
Views: 377829
Reputation: 1
get_or_create() returns the tuple which contains 2 values and the 1st value is an object and the 2nd value is the boolean value which indicates that a new object is created or not as shown below:
# 1st # 2nd
(object, boolean)
So, if you want both an object and a boolean value, put one more variable created
after customer.source
as shown below:
# Here
customer.source, created = Source.objects.get_or_create(name="Website")
# object # boolean
And, if you want only an object without a boolean value, put [0]
just after get_or_create()
as shown below:
# Here ↓↓↓
customer.source = Source.objects.get_or_create(name="Website")[0]
# object
And, if you want only a boolean value without an object put [1]
just after get_or_create()
as shown below:
# Here ↓↓↓
created = Source.objects.get_or_create(name="Website")[1]
# boolean
Upvotes: 4
Reputation: 1225
Important warning.
you should take care of the following before using the get_or_create , https://docs.djangoproject.com/en/4.0/ref/models/querysets/. .... Warning
This method is atomic assuming that the database enforces uniqueness of the keyword arguments (see unique or unique_together). If the fields used in the keyword arguments do not have a uniqueness constraint, concurrent calls to this method may result in multiple rows with the same parameters being inserted.
Upvotes: 1
Reputation: 11
get_or_create method would actually return a tuple.
The trick with the get_or_create method is that it actually returns a tuple of (object, created). The first element is an instance of the model you are trying to retrieve and the second is a boolean flag to tell if the instance was created or not. True means the instance was created by the get_or_create method and False means it was retrieved from the database
So you can do something like to get the source instance
``` customer.source = Source.objects.get_or_create(name="Website")[0]
```
Upvotes: 1
Reputation: 1479
get_or_create()
returns a tuple:
customer.source, created = Source.objects.get_or_create(name="Website")
created
→ has a boolean value, is created or not.
customer.source
→ has an object of get_or_create()
method.
Upvotes: 35
Reputation: 11211
From the documentation get_or_create:
# get_or_create() a person with similar first names.
p, created = Person.objects.get_or_create(
first_name='John',
last_name='Lennon',
defaults={'birthday': date(1940, 10, 9)},
)
# get_or_create() didn't have to create an object.
>>> created
False
Explanation:
Fields to be evaluated for similarity, have to be mentioned outside defaults
. Rest of the fields have to be included in defaults
. In case CREATE event occurs, all the fields are taken into consideration.
It looks like you need to be returning into a tuple, instead of a single variable, do like this:
customer.source,created = Source.objects.get_or_create(name="Website")
Upvotes: 532
Reputation: 273
Following @Tobu answer and @mipadi comment, in a more pythonic way, if not interested in the created flag, I would use:
customer.source, _ = Source.objects.get_or_create(name="Website")
Upvotes: 24
Reputation: 898
The issue you are encountering is a documented feature of get_or_create
.
When using keyword arguments other than "defaults" the return value of get_or_create
is an instance. That's why it is showing you the parens in the return value.
you could use customer.source = Source.objects.get_or_create(name="Website")[0]
to get the correct value.
Here is a link for the documentation: http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kwargs
Upvotes: 7
Reputation: 25426
get_or_create
returns a tuple.
customer.source, created = Source.objects.get_or_create(name="Website")
Upvotes: 46