如何在模型中没有表达的 FK 关系的管理更改页面中的字段上实现添加/编辑链接?

问题描述

我有一个 Django 3.x 网站。有 3 个模型,其中包括 DocumentMetaDataMetaDataValueMetaDataValue 模型与 MetaData 模型具有外键关系。

一个简单的世界中,会有一个MetaDataDocument 的外键关系。然后 DocumentAdmin 会将 MetaData 字段显示为下拉列表,并填充相应的 MetaDataValues。下拉菜单旁边还会有编辑/添加(铅笔/加号)链接,以允许用户编辑/添加MetaDataValue 对象的 MetaData

但是,该项目的要求之一是在运行时之前不定义哪些或多少 MetaData 对象将与特定的 Document 类型相关联。这些关联是通过另一组模型进行的。因此,Document 管理更改页面在运行时将不同的 MetaData 字段添加到更改管理页面方法是查看 MetaData 字段与此类 {{ 1}},然后通过 Document 方法将它们添加到字段集。

这种设计的含义是不能编辑/添加值到 get_fieldsets 管理更改页面上的特定 MetaData 字段,因为我认为 Django 丢失了DocumentDocument 模型,因为字段集是在管理员MetaData 方法生成的。

我可以添加代码页来显示 get_fieldsets 字段是如何在运行时生成的,但我认为这不会使描述更加清晰。我查看了为上述“简单世界”示例生成页面代码和字段集,但看不到 Django 在哪里确定何时将编辑/更改链接添加到特定外键字段的下拉列表。>

我的问题是,如何将铅笔和加号添加MetaData 管理更改页面显示的这些 MetaData 字段,并让用户选择添加/编辑 {{1 }} 对于那个特定的 Document 对象?我可以创建一些 Ajax 调用并自己完成所有繁重的工作,但我更愿意尽可能多地利用 Django 基础设施,而不是重新发明更多。

谢谢!

标记

解决方法

我找到了使用 RelatedFieldWidgetWrapper 的解决方案。我将这个小部件包装器添加到我所有需要绿色加号(添加)和黄色铅笔(编辑)的选择中。

这里有太多代码要发布,但这里是它的主要内容。我的数据库表 MetaData 包含所有字段的名称,MetaDataValue 包含每个元数据字段的值。元数据用于描述文档(文本、视频、图像),但 MetaData 模型和 Document 模型之间没有 FK 关系。元数据和文档之间的关系包含在另一个表的 JSON 字段中。 MetaData 表还具有用于该元数据字段的 Django 字段类型。还有另一个表用于确定哪些元数据字段适用于哪种文档类型(图像、文本、视频)。对于所有 ModelChoiceFields,我添加了字段和小部件(Select 包裹在 RelatedFieldWidgetWrapper 中)。

elif (metadata_names[i].field_type == MetaData.MODELCHOICEFIELD):
            fields[metadata_names[i].name] = forms.ModelChoiceField(queryset=MetaDataValue.objects.filter(metadata_id=metadata_names[i].metadata_id).order_by('value'),required=False,label=metadata_names[i].label,help_text=metadata_names[i].help_text)
            # add the green plus (add) and pencil (edit) links to each select field
            fields[metadata_names[i].name].widget = RelatedFieldWidgetWrapper(fields[metadata_names[i].name].widget,MetaDataValue._meta.get_field('tag_value'),admin_site,can_add_related=True,can_change_related=True)  
            if 'documentType_id' in fields:
                # Editing/add a new document type seems like a bad idea,as document type is used a lot in the processing logic
                fields['documentType_id'].widget.can_add_related = False
                fields['documentType_id'].widget.can_change_related = False

困难的部分是为 RelatedFieldWidgetWrapper 获取正确的参数。该小部件的文档有点稀少,因为我认为它是管理的早期部分,但是自从首次实现以来,Django 代码的大部分内容都发生了变化,因此过去使用此包装器的方式很多(即堆栈溢出帖子)已被弃用。我只是查看了来源,并尝试了似乎合适的方法,直到它起作用为止。最后,这些文章很有帮助:

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...