La documentation Django ne répertorie que des exemples de remplacement save()
et delete()
. Cependant, j'aimerais définir un traitement supplémentaire pour mes modèles uniquement lorsqu'ils sont créés . Pour quiconque connaît Rails, cela équivaudrait à créer un :before_create
filtre. Est-ce possible?
la source
create
? C'est une solution intéressante, mais cela ne fonctionnerait pas dans les cas où l'objet est créé en utilisantObject(**kwargs).save()
ou toute autre variation à ce sujet.super(MyModel, self).save(*args, **kwargs)
?self.pk
n'est peut-être pas la meilleure option pour vérifier si l'objet vient d'être créé ou s'il est simplement mis à jour. Parfois, vous fournissez un identifiant d'objet au moment de la création (une valeur personnalisée non générée par la base de données, commeKSUID
), et cette clause ne s'exécutera jamais ... Il y a uneself._state.adding
valeur pour s'assurer qu'elle est enregistrée pour la première fois ou simplement mise à jour, ce qui aide dans ces cas.un exemple de création d'un signal post_save (à partir de http://djangosnippets.org/snippets/500/ )
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): """Create a matching profile whenever a user object is created.""" if created: profile, new = UserProfile.objects.get_or_create(user=instance)
voici une discussion approfondie pour savoir s'il est préférable d'utiliser des signaux ou des méthodes de sauvegarde personnalisées https://web.archive.org/web/20120815022107/http://www.martin-geber.com/thought/2007/10/29/ django-signaux-vs-méthode-de-sauvegarde-personnalisée /
À mon avis, l'utilisation de signaux pour cette tâche est plus robuste, plus facile à lire mais plus longue.
la source
instance.save()
. Donc, dans ce cas, il y a également une pénalité de performances car il y aura une requête INSERT et une requête UPDATE dans la base de données.C'est vieux, a une réponse acceptée qui fonctionne (celle de Zach), et une plus idiomatique aussi (celle de Michael Bylstra), mais comme c'est toujours le premier résultat sur Google que la plupart des gens voient, je pense que nous avons besoin d'un plus de bonnes pratiques modernes-django réponse de style ici :
from django.db.models.signals import post_save class MyModel(models.Model): # ... @classmethod def post_create(cls, sender, instance, created, *args, **kwargs): if not created: return # ...what needs to happen on create post_save.connect(MyModel.post_create, sender=MyModel)
Le point est le suivant:
@classmethod
au lieu de@staticmethod
parce que vous devrez probablement faire référence à des membres de classe statiques dans le codeEncore plus propre serait si le noyau Django avait un
post_create
signal réel . (Imho si vous devez passer un argument booléen pour changer le comportement d'une méthode, cela devrait être 2 méthodes.)la source
Pour répondre littéralement à la question, la
create
méthode dans le gestionnaire d'un modèle est un moyen standard de créer de nouveaux objets dans Django. Pour remplacer, faites quelque chose commefrom django.db import models class MyModelManager(models.Manager): def create(self, **obj_data): # Do some extra stuff here on the submitted data before saving... # For example... obj_data['my_field'] = my_computed_value(obj_data['my_other_field']) # Now call the super method which does the actual creation return super().create(**obj_data) # Python 3 syntax!! class MyModel(models.model): # An example model my_field = models.CharField(max_length=250) my_other_field = models.CharField(max_length=250) objects = MyModelManager()
Dans cet exemple, je remplace la méthode de la méthode du gestionnaire
create
pour effectuer un traitement supplémentaire avant que l'instance ne soit réellement créée.REMARQUE: Code comme
my_new_instance = MyModel.objects.create(my_field='my_field value')
exécutera cette
create
méthode modifiée , mais un code commemy_new_unsaved_instance = MyModel(my_field='my_field value')
Ne fera pas.
la source
Le remplacement
__init__()
vous permettra d'exécuter du code lorsque le modèle est instancié. N'oubliez pas d'appeler les parents__init__()
.la source
Vous pouvez remplacer la méthode create avec un gestionnaire personnalisé ou ajouter une méthode de classe sur la classe de modèle. https://docs.djangoproject.com/en/1.11/ref/models/instances/#creating-objects
la source
La réponse préférée est correcte, mais le test pour savoir si l'objet est en cours de création ne fonctionne pas si votre modèle dérive de UUIDModel. Le champ pk aura déjà une valeur.
Dans ce cas, vous pouvez faire ceci:
already_created = MyModel.objects.filter(pk=self.pk).exists()
la source