如何在Django管理界面中添加双向多对多字段?

11 投票
3 回答
2288 浏览
提问于 2025-04-15 13:54

在我的models.py文件里,我有这样的内容:

class LocationGroup(models.Model):
    name = models.CharField(max_length=200)

class Report(models.Model):
    name = models.CharField(max_length=200)
    locationgroups = models.ManyToManyField(LocationGroup)

admin.py(标准设置):

admin.site.register(LocationGroup)
admin.site.register(Report)

当我进入报告的管理页面时,它显示了一个很不错的多选框。请问我怎么才能在LocationGroup里也添加一个相同的多选框呢?我可以通过调用LocationGroup.report_set.all()来访问所有的报告。

3 个回答

1

我觉得你想要的功能是管理后台的内联功能。在你的admin.py文件中,你需要添加类似下面的代码:

class LocationGroupInline(admin.TabularInline):
    model = LocationGroup

class ReportAdmin(admin.ModelAdmin):
    inlines = [ LocationGroupInline, ]
admin.site.register(Report, ReportAdmin)
admin.site.register(LocationGroup)

在LocationGroupInline中有很多选项可以让你进一步设置相关模型的内联显示。其中两个选项是formformset,这可以让你使用自定义的Django表单和表单集类,来更好地调整内联模型在后台的显示效果。通过这个功能,你可以创建一个简单的表单,只显示你想要的多选字段(不过对于多对多字段,不能显示成单个下拉框,只能是多选框)。举个例子:

class MyLocationGroupForm(forms.Form):
    location = forms.MultipleModelChoiceField(
           queryset=LocationGroup.objects.all())

class LocationGroupInline(admin.TabularInline):
    model = LocationGroup
    form = MyLocationGroupForm
2

我觉得你可以把这个示例代码(来源)和一个会破坏sync_db的代码结合起来

class ItemType(meta.Model):
    name = meta.CharField(maxlength=100)
    description = meta.CharField(maxlength=250)
    properties = meta.ManyToManyField('PropertyType',
            db_table='app_propertytype_itemtypes')

class PropertyType(meta.Model):
    name = meta.CharField(maxlength=100)
    itemtypes = meta.ManyToManyField(ItemType)

还有这个代码片段

class ManyToManyField_NoSyncdb(models.ManyToManyField):
    def __init__(self, *args, **kwargs):
        super(ManyToManyField_NoSyncdb, self).__init__(*args, **kwargs)
       self.creates_table = False

这样你就能得到类似的东西

class ItemType(meta.Model):
    name = meta.CharField(maxlength=100)
    description = meta.CharField(maxlength=250)
    properties = meta.ManyToManyField_NoSyncdb('PropertyType',
            db_table='app_propertytype_itemtypes')

class PropertyType(meta.Model):
    name = meta.CharField(maxlength=100)
    itemtypes = meta.ManyToManyField(ItemType)

免责声明:这只是一个粗略的想法

补充:可能和Django的1.1代理模型有关

8

我找到的解决办法是按照这个链接的说明来操作:使用中介模型的多对多字段。虽然你并没有使用“通过”模型的功能,但可以假装你在用,然后创建一个简单的模型,并加上必要的外键。

# models:  make sure the naming convention matches what ManyToManyField would create
class Report_LocationGroups(models.Model):
    locationgroup = models.ForeignKey(LocationGroup)
    report = models.ForeignKey(Report)

# admin
class ReportInline(admin.TabularInline):
    model = models.Report_LocationGroups

class LocationGroupAdmin(admin.ModelAdmin):
    inlines = ReportInline,

撰写回答