167 votes

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

Je veux créer un objet modèle, comme Person, si l'id de la personne n'existe pas, ou je vais obtenir cet objet person.

Le code pour créer une nouvelle personne est le suivant :

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.

273voto

Zags Points 582

Il n'est pas clair si votre question demande le obtenir_ou_créer (disponible depuis au moins Django 1.3) ou la méthode actualiser_ou_créer (nouveau dans Django 1.7). Cela dépend de la façon dont vous voulez mettre à jour l'objet utilisateur.

L'exemple d'utilisation est le suivant :

# 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}
)

204voto

bakkal Points 13449

Si vous cherchez le cas d'utilisation "mettre à jour si existant sinon créer", veuillez vous référer à @Zags excellente réponse


Django dispose déjà d'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

11voto

Aamir Adnan Points 10903

Django a un support pour cela, vérifiez obtenir_ou_créer

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

11voto

Pour un petit nombre d'objets seulement, l actualiser_ou_créer fonctionne bien, mais si vous travaillez sur une grande collection, cette méthode ne sera pas adaptée. actualiser_ou_créer exécute toujours d'abord un SELECT et ensuite 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)

Au mieux, cela n'exécutera que la première requête de mise à jour, et seulement s'il n'y a pas de lignes correspondantes, une autre requête d'insertion. Ce qui augmentera considérablement vos performances si vous vous attendez à ce que la plupart des lignes existent réellement.

Tout dépend cependant de votre cas d'utilisation. Si vous vous attendez surtout à des insertions, alors peut-être que l'option bulk_create() pourrait être une option.

4voto

Tom Manterfield Points 2840

J'ai pensé ajouter une réponse puisque le titre de votre question semble demander 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 vouliez créer ou mettre à jour un objet, la méthode .save() a déjà ce comportement par défaut, à partir de les docs :

Django fait abstraction de la nécessité d'utiliser les 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 comme une valeur qui évalue à True (c'est-à-dire une valeur autre que None ou la chaîne vide), Django exécute un UPDATE. Si l'attribut de clé primaire de l'objet n'est pas défini ou si l'UPDATE n'a rien mis à jour, Django exécute un INSERT.

Il est intéressant de noter que lorsqu'ils disent "si l'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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X