Django, автоматическая настройка поля во время сохранения на основе других входов страницы администратора - PullRequest
0 голосов
/ 11 декабря 2011

Я ищу правильный способ установить полное имя в экземпляре SuperPerson.

class Suffix(models.Mode):
    suffix = models.CharField(max_length=255)
    def __unicode__(self):
        return u'%s'%(self.suffix)

class Person(models.Model):
    first_name= models.CharField(max_length=255)
    last_name= models.CharField(max_length=255)
    suffixes= models.ManyToManyField(Suffix, blank=True, null=True)
    full_name= models.CharField(max_length=255)

class SuperPerson(Person):
    ignore_this_field= model.CharField(max_length=255)

полное имя скрыто от пользователя на странице администратора и должно автоматически обновляться на основе других входных данных.на странице администратора, когда нажата кнопка сохранения на странице администратора.

Я попытался переопределить сохранение, как это, и варианты:

def save(self, *args, **kwargs):
    # Attempt to get data into the database so I can access it
    super(SuperPerson,self).save(*args,**kwargs)

    self.full_name = self.first_name + self.last_name 
    for suf in self.suffixes.all():
        self.full_name+= suf.__unicode__()

    # Now save the copy with full_name set as I wish
    super(SuperPerson,self).save(*args,**kwargs)

Этот метод работает, если я нажму кнопку сохранения на странице администраторадважды, что неприемлемо для моих случаев использования, похоже, что новые self.suffixes, которые я ввел со страницы администратора, не попали в базу данных с первым super.save, когда я вызываю self.suffixes.all ().

Я попытался сделать full_name свойством с помощью decorator, но мне также нужно иметь возможность фильтровать базы данных Person и SuperPerson по full_name, чтобы это не сработало, если кто-то не подскажет мне, как фильтровать свойство.Хотя я предпочел бы сохранить значение в БД.

Я пробовал сигналы pre_save и post_save - ни сработало.

@receiver(pre_save, sender=SuperPerson)
def set_full_name(sender, instance, **kwargs):
    instance.full_name = instance.first_name + instance.last_name

    for suf in instance.suffixes.all():
        instance.full_name+= ', ' + suf.__unicode__()

Редактировать: - это имеет тот же эффект - суффиксы экземпляра несоответствует тому, что было на странице администратора.

Как правильно сохранить полное имя на основе других входных данных?Да, и я надеюсь избежать путаницы с формами администратора.

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: Кажется, проблема именно в том, что поле суффиксов не обновляется, когда я пытаюсь его использовать.Я могу обновить full_name на что-то другое, например, добавив строку, представляющую текущую дату, я просто не могу получить доступ к суффиксам.

Спасибо, Дейл

РЕШЕНИЕ:

@receiver(m2m_changed, sender=Person.suffixes.through)
def set_full_name_after_ManyToMany_saved(sender, instance, **kwargs):
    instance.full_name = instance.first_name + instance.last_name
    for suf in instance.suffixes.all():
        instance.full_name+= ', ' + suf.__unicode__()
    print 'Saving As', instance.full_name
    instance.save()

Мне любопытно, почему мне пришлось использовать Person.suffixes.through вместо SuperPerson, Suffixes или Person.suffixes - где-то есть хорошая документация, я не смог ее найти.И он запускает код 4 раза, но, по крайней мере, в конечном итоге получает правильный результат.

Большое спасибо Дэнни и Бурхану

1 Ответ

2 голосов
/ 11 декабря 2011

Проблема в том, что ваши отношения m2m с Suffix или, скорее, способ, которым администратор django сохраняет отношения m2m.

Довольно хорошее объяснение в этом ответе на Почему добавление сайта к объекту не 'Кажется, что он работает в переопределении save () в администраторе Django?

Когда вы сохраняете модель через формы администратора, это не атомарная транзакция.Сначала основной объект сохраняется (чтобы убедиться, что у него есть PK), затем M2M очищается, и новые значения, установленные для того, что появилось в форме.

post_save () на самом деле еще слишком рано.Вот где был сохранен экземпляр, а не его отношения.

Вам необходимо подключиться к сигналу m2m_changed: https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed

или дождаться Django 1.4, где ModelAdmin выдает «когда все будет сделано»."сигнал: https://code.djangoproject.com/ticket/16115

...