Django сохранить предыдущий объект из моделей

На админ-сайте Django у меня есть этот класс. Я хочу сохранить предыдущую версию объекта (Серверы), который является многотоновым полем для поиска изменений на объекте.

При нормальной работе CharField эта работа, но для многих томаных полей я получил эту ошибку:

"<SourceDestinationGroup: asdas>" needs to have a value for field "id" before this many-to-many relationship can be used.

вот мой объектный класс

class SourceDestinationGroup(models.Model):
    STATE_CHOICES = (
        ('C', 'in Change'),
        ('F', 'Finished')
        )
    ServerGroupName = models.CharField(max_length=256)
    Description = models.CharField(max_length=256,blank=True)
    Servers = models.ManyToManyField(Server)
    Status = models.CharField(max_length=1, choices=STATE_CHOICES, default='C')



    def __init__(self, *args, **kw):
        super(SourceDestinationGroup, self).__init__(*args, **kw)
        self._old_Servers = self.Servers

    def save(self, **kw):
       if self.Servers != self._old_Servers:
            self.Status = 'C'
            self._old_Servers = self.Servers

        super(SourceDestinationGroup, self).save(**kw)



   def __str__(self):
       return self.ServerGroupName

Ответ 1

Соотношения M2M не сохраняются как часть метода save(). В администраторе главный объект сохраняется, а затем сохраняется отношение m2m; поэтому, сериализируя список тегов в методе сохранения, вы печатаете значение тегов перед сохранением новых значений. Если вы хотите установить поведение "post m2m save", вам необходимо переопределить представление обновления самого администратора.

Ответ 2

Вы пытаетесь инициализировать атрибут ManyToMany (.Servers) при создании объекта.

Где бы вы ни пытались создать SourceDestinationGroup, вы должны, вероятно, создать его, ТОГО:

group.Servers = servers
group.save()

Или удалите атрибут Servers в методе init и перезагрузите его:

def __init__(self, *args, **kw):
    super(SourceDestinationGroup, self).__init__(*args, **kw)
    self._temp_Servers = self.Servers

def save(self, **kw):
    if self.id is None:
        self._temp_Servers = self.Servers
        self.Servers = None # Your 'Servers' attribute was still being set, hence raising an Exception in the super.save just after
    super(SourceDestinationGroup, self).save(**kw)
    if self._old_Servers is not None:
        self.Servers = self._temp_Servers 
        super(SourceDestinationGroup, self).save(**kw)

Ответ 3

Я столкнулся с этой проблемой несколько месяцев назад. Соотношения m2m не обновляются внутри метода save модели, даже если super() вызывается перед использованием этих отношений.

Единственный способ решения проблемы я нашел, чтобы написать отдельную функцию, которая имеет дело с m2m отношений, и вызывать его из save метод формы:

def save(self, *args, **kwargs):
    instance = super().save(*args, **kwargs)
    instance.update_m2m()
    return instance

В вашем случае эта функция почти такая же, как и метод save модели:

def update_m2m(self):
    if self.Servers != self._old_Servers:
       self.Status = 'C'
       self._old_Servers = self.Servers
       self.save()

Ответ 4

Ваш экземпляр SourceDestinationGroup должен быть сохранен в базе данных, прежде чем вы сможете добавить к нему какие-либо серверы. Вероятно, вы можете легко исправить это в своем методе save:

def save(self, **kw):
    if self.id is not None and self.Servers != self._old_Servers:
        self.Status = 'C'
        self._old_Servers = self.Servers

    super(SourceDestinationGroup, self).save(**kw)

Как я вижу, ваша смена сервера имеет смысл, когда есть какие-то старые значения.