J'ai un modèle que je voudrais contenir un nom de sujet et ses initiales (les données sont quelque peu anonymisées et suivies par des initiales).
En ce moment, j'ai écrit
class Subject(models.Model):
name = models.CharField("Name", max_length=30)
def subject_initials(self):
return ''.join(map(lambda x: '' if len(x)==0 else x[0],
self.name.split(' ')))
# Next line is what I want to do (or something equivalent), but doesn't work with
# NameError: name 'self' is not defined
subject_init = models.CharField("Subject Initials", max_length=5, default=self.subject_initials)
Comme indiqué par la dernière ligne, je préférerais pouvoir stocker les initiales dans la base de données en tant que champ (indépendant du nom), mais cela est initialisé avec une valeur par défaut basée sur le champ de nom. Cependant, j'ai des problèmes car les modèles django ne semblent pas avoir de «soi».
Si je change la ligne en subject_init = models.CharField("Subject initials", max_length=2, default=subject_initials)
, je peux faire la syncdb, mais je ne peux pas créer de nouveaux sujets.
Est-ce possible dans Django, avoir une fonction appelable donne une valeur par défaut à un champ en fonction de la valeur d'un autre champ?
(Pour les curieux, la raison pour laquelle je veux séparer les initiales de mon magasin séparément est dans de rares cas où les noms de famille bizarres peuvent être différents de ceux que je traque. Par exemple, quelqu'un d'autre a décidé que les initiales du sujet 1 nommé «John O'Mallory» sont "JM" plutôt que "JO" et souhaite le corriger, éditez-le en tant qu'administrateur.)
la source
super().save(*args, **kwargs)
(sans lesSubject, self
arguments) comme dans l'exemple de la documentation référencée.Je ne sais pas s'il existe une meilleure façon de faire cela, mais vous pouvez utiliser un gestionnaire de signal pour le
pre_save
signal :la source
post_save
au lieu depre_save
.**kwargs
ne dispose pas de l' argument que toutes les fonctions de récepteur devraient avoir selon docs.djangoproject.com/en/2.0/topics/signals/... ?save()
, peut-être changée en priorité__init__
, est meilleure car elle est plus explicite.En utilisant les signaux Django , cela peut être fait assez tôt, en recevant le
post_init
signal du modèle.Le
post_init
signal est envoyé par la classe une fois qu'elle a effectué l'initialisation sur l'instance. De cette façon, l'instance obtient une valeur pourname
avant de tester si ses champs non nullables sont définis.la source
save()
, peut-être changée en priorité__init__
, est meilleure car elle est plus explicite.Comme implémentation alternative de la réponse de Gabi Purcaru , vous pouvez également vous connecter au
pre_save
signal à l'aide dureceiver
décorateur :Cette fonction de récepteur prend également les
**kwargs
arguments de mot-clé génériques que tous les gestionnaires de signaux doivent prendre selon https://docs.djangoproject.com/en/2.0/topics/signals/#receiver-functions .la source