Comment utiliser correctement get_or_create?

203

J'essaie d'utiliser get_or_create pour certains champs de mes formulaires, mais j'obtiens une erreur 500 lorsque j'essaie de le faire.

L'une des lignes ressemble à ceci:

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

L'erreur que j'obtiens pour le code ci-dessus est:

Cannot assign "(<Source: Website>, False)": "Customer.source" 
   must be a "Source" instance.
Stephen
la source

Réponses:

353

De la 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

Explication: Les champs dont la similitude doit être évaluée doivent être mentionnés à l'extérieur defaults. Les autres champs doivent être inclus dans defaults. En cas d'événement CREATE, tous les champs sont pris en compte.

Il semble que vous deviez retourner dans un tuple, au lieu d'une seule variable, faites comme ceci:

customer.source,created = Source.objects.get_or_create(name="Website")
Bryan Rehbein
la source
3
FYI created est un booléen. Vrai si créé, Faux s'il est récupéré
Josh
3
Un supplémentaire save()est redondant?
zypro
@zypro C'est comme create(), créer un objet et tout sauvegarder en une seule étape et n'en a pas besoinsave()
Amin Mir
32

get_or_create renvoie un tuple.

customer.source, created = Source.objects.get_or_create(name="Website")
Tobu
la source
16
Ou, si vous ne vous souciez pas du drapeau booléen:customer.source = Source.objects.get_or_create(name="Website")[0]
mipadi
7
@mipadi Je préfère customer.source, _ = Source.objects.get_or_create(name="Website"), car cela rend le fait qu'un tuple a été retourné plus évident, ce qui permet d'éviter de futurs bugs.
Solomon Ucko
15

get_or_create() renvoie un tuple:

customer.source, created  = Source.objects.get_or_create(name="Website")
  • created a une valeur booléenne, est créé ou non.

  • customer.source a un objet de get_or_create()méthode.

Tushar.PUCSD
la source
12

Après la réponse @Tobu et le commentaire @mipadi, d'une manière plus pythonique, si le drapeau créé ne m'intéresse pas, j'utiliserais:

customer.source, _ = Source.objects.get_or_create(name="Website")
jbondia
la source
4

Le problème que vous rencontrez est une caractéristique documentée de get_or_create.

Lorsque vous utilisez des arguments de mot-clé autres que "par défaut", la valeur de retour de get_or_createest une instance. C'est pourquoi il vous montre les parens dans la valeur de retour.

vous pouvez utiliser customer.source = Source.objects.get_or_create(name="Website")[0]pour obtenir la valeur correcte.

Voici un lien pour la documentation: http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kwargs

wlashell
la source