137 votes

Django Model Field par défaut basé sur un autre champ dans le même modèle

J'ai un modèle que je tiens à contenir des matières nom et ses initiales. (Les données sont quelque peu anonyme et suivis par des initiales.)

Maintenant, je l'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ère être en mesure d'avoir les initiales réellement obtenir stockées dans la base de données comme un champ (indépendant de nom), mais qui est initialisé avec une valeur par défaut basée sur le champ nom. Cependant, je vais avoir des questions comme django modèles ne semblent pas avoir un "moi".

Si je change la ligne d' subject_init = models.CharField("Subject initials", max_length=2, default=subject_initials),, je peux faire le syncdb, mais ne peuvent pas créer de nouveaux sujets.

Est-ce possible dans django, ayant une fonction appelable donner une valeur par défaut à un champ basé sur la valeur d'un autre champ?

(Pour les curieux, la raison pour laquelle je veux me séparer de mon magasin initiales séparément dans les rares cas où étranges noms de famille peuvent avoir différentes que celles que je suis suivi. E. g., quelqu'un d'autre a décidé que l'Objet 1 Nommé "John O'Mallory" initiales "JM" plutôt que "JO" et veut résoudre le modifier en tant qu'administrateur.)

128voto

Elf Sternberg Points 9764

Les modèles d'il y a donc bien un "soi"! C'est juste que vous êtes en train de définir un attribut d'une classe de modèle comme étant dépendant d'une instance du modèle; ce n'est pas possible, que l'instance n'a pas (et ne peut) pas exister avant votre définissent la classe et ses attributs.

Pour obtenir l'effet que vous souhaitez, remplacer la méthode save() de la classe du modèle. Faire toutes les modifications que vous souhaitez à l'instance nécessaire, puis d'appeler la super-classe de la méthode de faire de réelles économies. Voici un exemple rapide.

def save(self, *args, **kwargs):
    if not self.subject_init:
        self.subject_init = self.subject_initials()
    super(Subject, self).save(*args, **kwargs)

Ce sujet est couvert en Surchargeant les Méthodes de Model dans la documentation.

19voto

Gabi Purcaru Points 15158

Je ne sais pas s'il ya une meilleure façon de le faire, mais vous pouvez utiliser un `` gestionnaire:

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