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.

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")

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")

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.


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")

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.