我的具体问题详述如下,但我的问题的主要观点是:当我点击"保存"在编辑模型时,在Django管理表单上,会发生什么?验证/保存过程的顺序是什么?我如何覆盖这些方法来解决下面的问题,也就是说在适当的时候更新中间表作为我描述的问题的解决方法?
我正在研究面向PostgreSQL数据库的Django应用程序。数据库相对较大,我有很多多对多的关系。我目前遇到的问题是人与源之间的n:m关系。
该应用程序主要由非技术人员使用,通过Django的内置管理功能添加到数据库中。当我开始处理应用程序时,我遇到的主要问题是在管理站点上编辑人员时页面速度严重下降。如果此人拥有太多的源,则TabularInline表示源中的每个下拉列表都会加载数千个条目。我发现了一种解决方法并覆盖了get_formfield_for_foreignkey()
方法,如下所示:
def formfield_for_foreignkey(self, db_field, request, **kwargs):
field = super(SourceMaterialInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
# We will overwrite this method to ONLY return relevant materials on this person
materials = SourceMaterial.objects.all()
materials_p = SourceMaterial.people.through.objects.all()
person_ID = get_ID_from_path(request.path)
if not_integer(person_ID):
return field
materials_pid = materials_p.filter(person_id=person_ID)
# The next step is to use these relevant materials to obtain the SourceMaterial objects from the SourceMaterial table
relevant_ids = []
for mat in materials_pid:
relevant_ids += [mat.sourcematerial_id]
relevant_materials = materials.filter(id__in=relevant_ids)
# now we can set the queryset so that only relevant materials are included
field.queryset = relevant_materials
return field
所以这完成了我想要的。当您通过Admin页面编辑Person对象时,选择源的下拉菜单仅加载并显示属于该Person的Source。
然而,这会产生的问题是当我通过Person更改表单添加新的Source时。我想保留这个功能,但它现在已经坏了。
如果我要添加新来源,则会出现一个弹出窗口。我在我的机器上选择文件,给它命名并单击添加。此时,它将添加到Sources表中,但不会添加到将其链接到此Person的中间表中。当我去保存Person时,表单要求我更正此错误:选择一个有效的选择。这个选择不是可用的选择之一。
以下是弹出窗口:Add new source material pop-up for clarity
这是有道理的,因为人与源之间尚未建立联系。所以我在尝试以这种方式添加源时也尝试添加Person ID,错误是:Sourcematerial-person与此Sourcematerial和Person的关系已经存在。我假设这是因为当我添加具有Person ID的Source时,中间表被适当地填充,当我去保存时,它尝试再次添加源,因为表单将其检测为新的。
我希望我可以覆盖表单验证/保存,这样我就可以保持以这种方式向数据库添加Source的功能。如果有人对我可以覆盖的内容(我对文档非常困惑)或其他解决方案有任何建议,那就太棒了。谢谢!