【问题标题】:How to add bi-directional manytomanyfields in django admin?如何在 django admin 中添加双向多字段?
【发布时间】:2009-08-27 07:31:08
【问题描述】:

在我的 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)

当我进入 Report 的管理页面时,它会显示一个不错的多项选择字段。如何在 LocationGroup 中添加相同的多项选择字段?我可以通过调用 LocationGroup.report_set.all() 访问所有报告

【问题讨论】:

标签: python django django-models


【解决方案1】:

我找到的解决方法是按照ManyToManyFields with intermediary models 的说明进行操作。即使您没有使用“直通”模型功能,也可以假装您使用过,并使用必要的 ForeignKey 创建一个存根模型。

# 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,

【讨论】:

  • 最简单,但仍然是 hack。我希望 Django 能以更优雅的方式支持这一点。
【解决方案2】:

我认为你可以结合这个示例代码 (source) 来破坏 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)

this snippet

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's 1.1 Proxy Models有关

【讨论】:

    【解决方案3】:

    我想你要找的是admin inlines。在您的 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 Form 和 FormSet 类来进一步自定义内联模型管理员的外观。使用它,您可以创建一个简单的表单,该表单仅显示您想要的多项选择字段(除了 M2M 字段,它不能显示为单个下拉列表,而是一个多选框)。例如:

    class MyLocationGroupForm(forms.Form):
        location = forms.MultipleModelChoiceField(
               queryset=LocationGroup.objects.all())
    
    class LocationGroupInline(admin.TabularInline):
        model = LocationGroup
        form = MyLocationGroupForm
    

    【讨论】:

    • 报告管理员默认会内联 LocationGroups,问题是如何做相反的事情。无论如何,这将引发 LocationGroup 没有针对 ReportAdmin 的 ForeignKey 的异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 2023-01-13
    • 2021-04-02
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多