在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
M2M关系不会保存为save()方法的一部分。
在admin中,保存主对象,然后保存m2m关系;因此,通过序列化save方法中的标记列表,您可以在保存新值之前打印标记的值。
如果要安装“post m2m save”行为,则需要覆盖管理员本身的更新视图。
您正在尝试在创建对象时初始化ManyToMany属性(.Servers)。
无论您何时尝试创建SourceDestinationGroup,都应该创建它 然后 做:
group.Servers = servers
group.save()
要么, 去掉 init方法中的Servers属性,然后重置它:
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)
我几个月前遇到过这个问题。 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()
你的 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)
正如我所看到的,只有存在任何旧值时,您的服务器更改才有意义。