Подтвердить что ты не робот

Поле модели Django по умолчанию основано на другом поле в той же модели

У меня есть модель, в которой я хотел бы указать название темы и ее инициалы. (Данные несколько анонимны и отслеживаются инициалами.)

Прямо сейчас, я написал

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)

Как указано в последней строке, я предпочел бы, чтобы инициалы фактически сохранялись в базе данных как поле (независимо от имени), но оно инициализируется значением по умолчанию, основанным на поле имени. Однако у меня возникают проблемы, поскольку модели django, похоже, не имеют "я".

Если я изменил строку на subject_init = models.CharField("Subject initials", max_length=2, default=subject_initials), я могу сделать syncdb, но не могу создать новые темы.

Возможно ли это в django, если вызываемая функция дает по умолчанию какое-либо поле, основанное на значении другого поля?

(Любопытно, что причина, по которой я хочу отделить свои инициалы магазина отдельно, в редких случаях, когда странные фамилии могут отличаться от тех, которые я отслеживаю. Например, кто-то другой решил, что тема 1 названа "John O'Mallory" Инициалы - это "JM", а не "JO", и вы хотите исправить его как администратора.)

4b9b3361

Ответ 1

Модели, безусловно, имеют "я"! Просто вы пытаетесь определить атрибут класса модели как зависящий от экземпляра модели; это невозможно, поскольку экземпляр не существует (и не может) существовать до того, как вы определите класс и его атрибуты.

Чтобы получить нужный эффект, переопределите метод save() класса модели. Внесите необходимые изменения в необходимый экземпляр, затем вызовите метод суперкласса для фактической экономии. Вот краткий пример.

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

Это описано в Переопределение методов модели в документации.

Ответ 2

Я не знаю, есть ли лучший способ сделать это, но вы можете использовать обработчик сигналов для сигнал pre_save:

from django.db.models.signals import pre_save

def default_subject(sender, instance, using):
    if not instance.subject_init:
        instance.subject_init = instance.subject_initials()

pre_save.connect(default_subject, sender=Subject)