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)
Как я вижу, ваша смена сервера имеет смысл, когда есть какие-то старые значения.