Правильный способ использовать get_or_create?

203

Я пытаюсь использовать get_or_create для некоторых полей в моих формах, но я получаю ошибку 500, когда пытаюсь это сделать.

Одна из строк выглядит так:

customer.source = Source.objects.get_or_create(name="Website")

Ошибка, которую я получаю для приведенного выше кода:

Cannot assign "(<Source: Website>, False)": "Customer.source" 
   must be a "Source" instance.
Стивен
источник

Ответы:

353

Из документации 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

Пояснение: Поля, которые должны оцениваться на сходство, должны быть упомянуты снаружи defaults. Остальные поля должны быть включены в defaults. В случае возникновения события CREATE учитываются все поля.

Похоже, вам нужно возвращаться в кортеж, а не в одну переменную, сделайте так:

customer.source,created = Source.objects.get_or_create(name="Website")
Брайан Ребейн
источник
3
К вашему сведению, это логическое значение. Истинно, если создано, Ложно, если получено
Джош
3
А save()лишний лишний?
Zypro
@zypro Это похоже на create()создание объекта и сохранение всего этого за один шаг и не нужноsave()
Amin Mir
32

get_or_create возвращает кортеж

customer.source, created = Source.objects.get_or_create(name="Website")
Tobu
источник
16
Или, если вы не заботитесь о customer.source = Source.objects.get_or_create(name="Website")[0]
булевом
7
@mipadi Я бы предпочел customer.source, _ = Source.objects.get_or_create(name="Website"), так как это делает факт, что кортеж был возвращен более очевидным, помогая избежать будущих ошибок.
Соломон Уцко
15

get_or_create() возвращает кортеж:

customer.source, created  = Source.objects.get_or_create(name="Website")
  • created имеет логическое значение, создано или нет.

  • customer.source имеет объект get_or_create()метода.

Tushar.PUCSD
источник
12

После ответа @Tobu и комментария @mipadi более питонным образом, если бы меня не интересовал созданный флаг, я бы использовал:

customer.source, _ = Source.objects.get_or_create(name="Website")
jbondia
источник
4

Проблема, с которой вы столкнулись, является задокументированной особенностью get_or_create.

При использовании аргументов ключевого слова, отличных от «по умолчанию», возвращаемое значение get_or_createявляется экземпляром. Вот почему он показывает вам парены в возвращаемом значении.

Вы можете использовать, customer.source = Source.objects.get_or_create(name="Website")[0]чтобы получить правильное значение.

Вот ссылка на документацию: http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kwargs

wlashell
источник