web-dev-qa-db-fra.com

Créer Django modèle ou mettre à jour s'il existe

Je veux créer un objet modèle, comme Personne, si l'identifiant de la personne n'existe pas ou je l'obtiendrai.

Le code pour créer une nouvelle personne comme suit:

class Person(models.Model):
    identifier = models.CharField(max_length = 10)
    name = models.CharField(max_length = 20)
    objects = PersonManager()

class PersonManager(models.Manager):
    def create_person(self, identifier):
        person = self.create(identifier = identifier)
        return person

Mais je ne sais pas où vérifier et obtenir l'objet personne existant.

93
user1687717

Si vous recherchez un cas d'utilisation "mettre à jour si existant, créez", veuillez vous référer à @ excellente réponse de Zags


Django a déjà un get_or_create, https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create

Pour vous cela pourrait être:

id = 'some identifier'
person, created = Person.objects.get_or_create(identifier=id)

if created:
   # means you have created a new person
else:
   # person just refers to the existing one
145
bakkal

Il est difficile de savoir si votre question demande la méthode get_or_create (disponible à partir de au moins Django 1.3) ou la méthode pdate_or_create (nouveauté dans Django 1,7). Cela dépend de la façon dont vous souhaitez mettre à jour l'objet utilisateur.

Exemple d'utilisation:

# In both cases, the call will get a person object with matching
# identifier or create one if none exists; if a person is created,
# it will be created with name equal to the value in `name`.

# In this case, if the Person already exists, its existing name is preserved
person, created = Person.objects.get_or_create(
        identifier=identifier, defaults={"name": name}
)

# In this case, if the Person already exists, its name is updated
person, created = Person.objects.update_or_create(
        identifier=identifier, defaults={"name": name}
)
147
Zags

Django a un support pour cela, cochez get_or_create

person, created = Person.objects.get_or_create(name='abc')
if created:
    # A new person object created
else:
    # person object already exists
9
Aamir Adnan

Je pensais que je pourrais ajouter une réponse puisque le titre de votre question semble indiquer comment créer ou mettre à jour, plutôt que d'obtenir ou de créer comme décrit dans le corps de la question.

Si vous voulez créer ou mettre à jour un objet, la méthode .save () a déjà ce comportement par défaut, à partir de la documentation :

Django résume la nécessité d'utiliser des instructions SQL INSERT ou UPDATE. Plus précisément, lorsque vous appelez save (), Django suit cet algorithme:

Si l’attribut de clé primaire de l’objet est défini sur une valeur évaluée comme étant True (c’est-à-dire une valeur autre que None ou la chaîne vide), Django exécute UPDATE. Si l’attribut de clé primaire de l’objet n’est pas défini ou si UPDATE n’a rien mis à jour, Django exécute un INSERT.

Il est intéressant de noter que lorsqu'ils disent "si UPDATE n'a rien mis à jour", ils font essentiellement référence au cas où l'identifiant que vous avez donné à l'objet n'existe pas déjà dans la base de données.

3
Tom Manterfield

update_or_create fonctionne bien pour une petite quantité d'objets, mais si vous le faites sur une grande collection, son évolution ne sera pas bonne. update_or_create exécute toujours d'abord un SELECT, puis un UPDATE.

for the_bar in bars:
    updated_rows = SomeModel.objects.filter(bar=the_bar).update(foo=100)
        if not updated_rows:
            # if not exists, create new
            SomeModel.objects.create(bar=the_bar, foo=100)

Dans le meilleur des cas, cela ne fera que lancer la première requête de mise à jour et si aucune ligne ne correspond à celle-ci, exécutez une autre requête INSERT. Ce qui augmentera considérablement vos performances si vous vous attendez à ce que la plupart des lignes soient réellement existantes.

Tout se résume cependant à votre cas d'utilisation. Si vous attendez principalement des insertions, alors peut-être que la commande bulk_create () pourrait être une option.

1
Andreas Bergström

Si l'une des entrées lors de la création est une clé primaire, cela suffira:

Person.objects.get_or_create(id=1)

Il se mettra automatiquement à jour s'il existe car deux données avec la même clé primaire ne sont pas autorisées.

1
Aminah Nuraini