问题 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

11278
2018-03-13 11:19


起源

请在您的问题中包含完整的堆栈跟踪 - trinchet
抱歉,我已经更改了代码,所以现在我收到了其他错误。 - Christian Frei
在调试时,我发现m2m的变化会对网站上的下一次保存产生影响。多数人安静奇怪。我可以更改m2m对象中的内容但我看到第二次保存时的更改。 - Christian Frei
请提供完整的堆栈跟踪。 - Antoine Pinsard
我解决了这个问题。问题是m2m对象不会在保存方法中更新自己。使用'm2m_changed'效果很好 - Christian Frei


答案:


M2M关系不会保存为save()方法的一部分。 在admin中,保存主对象,然后保存m2m关系;因此,通过序列化save方法中的标记列表,您可以在保存新值之前打印标记的值。 如果要安装“post m2m save”行为,则需要覆盖管理员本身的更新视图。


5
2018-03-16 14:28





您正在尝试在创建对象时初始化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)

4
2018-03-15 13:03





我几个月前遇到过这个问题。 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()

3
2018-03-15 13:15





你的 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)

正如我所看到的,只有存在任何旧值时,您的服务器更改才有意义。


1
2018-03-13 12:04



感谢那个建议。我试过这个但是errormsg是一样的。我认为问题始于init函数。 - Christian Frei