使用 Django admin 时未保存 ManyToMany 字段
我遇到了一个奇怪的问题,我希望这里的人能够提供一些线索。
我正在重写模型的 save() 方法,以在运行 super() 后向 ManyToMany 字段添加一些值。我的问题是,当我在 Django admin 中保存时,值似乎被添加到关系中,但随后又变为空。
但是,如果我从 manage.py shell
执行此操作,则它可以正常工作。
我在那里放置了两个打印语句,无论我是通过 Django admin 还是通过 shell 运行它,它们都会产生完全相同的输出。
class Store(models.Model):
holidays = models.ManyToManyField(StoreHoliday, blank=True)
copy_holidays_from = models.ForeignKey('Store', blank=True, null=True)
def save(self):
print '==== BEFORE SAVE:', self.holidays.all()
super(Store, self).save()
self.copy_holidays()
print '==== AFTER SAVE:', self.holidays.all()
def copy_holidays(self):
if self.pk and self.copy_holidays_from:
self.holidays.clear()
for h in self.copy_holidays_from.holidays.all():
self.holidays.add( h )
这是 print
语句的输出:
==== BEFORE SAVE: []
==== AFTER SAVE: [<StoreHoliday: 10 Mar 2010, Chuck Norris birthday (Closed)>]
有人对可能导致此问题的原因有任何建议吗?
编辑: 通过管理界面保存时,Django 似乎会丢弃 save() 中对 m2m 关系的所有手动更改。这与它处理表单的方式有关吗?
I'm experiencing a weird problem which I hope someone in here may be able to shed some light on.
I'm overriding the save() method of a model to add some values to a ManyToMany-field after running super(). My problem is that when I'm saving in Django admin the values seems to get added to the relationship but is then empty again.
If however I do it from manage.py shell
it works without problem.
I've put two print statements in there and they produce the exact same output regardless of if I'm running it via Django admin or via shell.
class Store(models.Model):
holidays = models.ManyToManyField(StoreHoliday, blank=True)
copy_holidays_from = models.ForeignKey('Store', blank=True, null=True)
def save(self):
print '==== BEFORE SAVE:', self.holidays.all()
super(Store, self).save()
self.copy_holidays()
print '==== AFTER SAVE:', self.holidays.all()
def copy_holidays(self):
if self.pk and self.copy_holidays_from:
self.holidays.clear()
for h in self.copy_holidays_from.holidays.all():
self.holidays.add( h )
This is the output of the print
statements:
==== BEFORE SAVE: []
==== AFTER SAVE: [<StoreHoliday: 10 Mar 2010, Chuck Norris birthday (Closed)>]
Does anyone have any suggestions on what might be causing this?
Edit: All manual changes to the m2m relationship in save() seems to be discarded by Django when saving through the admin interface. Is this related to how it processes the form?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
所以事实证明上述并不是正确的实现方法。通过重写 model_save(),该代码属于 StoreAdmin。
这就是我解决它的方法:
So it turns out the above was not the correct way to implement it. The code belonged in StoreAdmin, by overriding model_save().
This is how I solved it:
我今天可能遇到了同样的行为,是的,您假设它与 django 处理数据的方式有关是正确的。
django 管理员对 ManyToMany 字段的更改与实际对象的更改分开。 (请记住,m2m 保存在不同的数据库表中)。
就我而言,如果我没有在管理站点的 ManyToMany 字段中选择任何内容,这将转换为对 ManyToMany 关系的clear() 操作。您在 save() 方法中所做的所有操作都会被此清除立即删除。与我在 post_save 信号处理程序中所做的事情相同。
解决方案(对我来说)是将 ManyToMany 字段分隔为内联字段,以便在修改对象时它不会自动保存为空。
I probably ran into this same behaviour just today and yes, you are correct in assuming it's related to how django handles the data.
The django admin makes the changes to a ManyToMany field separately from changing the actual object. (Remember that the m2m is saved in a different database table).
In my case if I didn't select anything in the ManyToMany field in the admin site, this would translate into a clear()-operation on the ManyToMany relation. Everything you do in the save()-method is immediately removed by this clear. Same thing with stuff I did in the post_save signal handler.
The solution (for me) was to separate the ManyToMany-field into an inline so it doesn't automatically get saved as empty when modifying the object.
在 django 2,1,4 中我的解决方案是使用 save_lated()
In django 2,1,4 my solution was to use save_related()
就我而言,最终是因为我数据库中的所有主键序列都不同步(..._id_seq 表)。
解决该问题后(请参阅该问题的 StackOverflow 解决方案),我的 M2M 模型再次开始保存。
In my case, it ended up being because all of my primary key sequences in my database were out of sync (..._id_seq tables).
After fixing that issue (see this StackOverflow solution for that problem), my M2M models starting saving again.
对我来说,问题是管理员仅保存许多字段的最后选定的实例(选择的最后一个“假期”)。所以我必须重写 save_model 方法,如下所示:
我花了很多时间在它上面,其他解决方案不起作用,所以我希望它会有所帮助。
For me the problem that the admin was only saving the last selected instance of the many fields (last 'holiday' selected). So I had to override the save_model method such as this:
I spent a lot of time on it and other solutions were not working, so I hope it will help.
更新 m2m 以及更新您的模型之一的解决方案之一。
Django 1.11 及更高版本
在更新过程中,当您对 m2m 记录所做的更改未保存时,您可以观察到的行为,即使您在模型之一或信号中的保存方法中进行了更改,发生这种情况只是因为 m2m 形式在主对象更新后重写了所有记录。
这就是为什么,一步一步:
主对象已更新。
您的代码(在保存方法或信号中)进行了更改(您可以
看看它们,只需在 ModelAdmin 中放置一个断点):
不幸的是,这个解决方案的缺点是 - 您对 m2m 的更改将在单独的事务中执行。
One of the solutions to update m2m, along with updating one of your models.
Django 1.11 and higher
The behavior which you can observe during updating, when changes which you made with m2m records were not saved, even after you made them in a save method one of your models or in a signal, happens only because m2m form rewrites all records after the main object is updated.
This is why, step by step:
The main object is updated.
Your code(in a save method or in a signal) made changes (you can
look at them, just put a breakpoint in ModelAdmin):
Unfortunately, the downside of this solution - your changes with m2m will be executed in a separate transaction.