简体   繁体   English

在 Django admin 中显示多对多关系的双方

[英]Displaying both sides of a ManyToMany relationship in Django admin

Say I have the following models that have a many-to-many relationship:假设我有以下具有多对多关系的模型:

models.py:模型.py:

class Foo(models.Model):
    name = models.TextField()

class Bar(models.Model):
    name = models.TextField()
    foos = models.ManyToManyField(Foo, related_name='bars')

And then having defined them in admin in the following way:然后通过以下方式在管理员中定义它们:

admin.py管理员.py

@admin.register(Foo)
class FooAdmin(admin.ModelAdmin):
    pass

@admin.register(Bar)
class BarAdmin(admin.ModelAdmin):
    pass

In Django admin, when browsing Bar instances, I can see the Foo instances Bar is associated with and can modify them from there.在 Django admin 中,当浏览Bar实例时,我可以看到Bar关联的Foo实例,并且可以从那里修改它们。

However, no such luck with Foo , I can't see the Bar instances that every Foo object is associated with.但是, Foo没有这样的运气,我看不到每个 Foo object 与之关联的Bar实例。

Can Django define automatic handling for this or would I need to roll my own methond? Django 可以为此定义自动处理还是我需要推出自己的方法?

I'm using Python 3.6.1 and Django 1.11.我正在使用 Python 3.6.1 和 Django 1.11。

You could define a custom InlineModelAdmin like so: 您可以像这样定义自定义InlineModelAdmin

class BarInline(admin.TabularInline):
    model = Bar.foos.through

and use it in your FooAdmin : 并在你的FooAdmin使用它:

class FooAdmin(admin.ModelAdmin):
"""Foo admin."""
    model = Foo
    inlines = [
        BarInline,
    ]

Have a look at this part of the django documentation . 看看django 文档的这一部分。

You can define custom fields for list_display like this: 您可以像这样为list_display定义自定义字段:

@admin.register(Foo)
class FooAdmin(admin.ModelAdmin):
    """Foo admin."""

    list_display = ('name', 'get_bars')
    search_fields = ('name',)

    def get_bars(self, obj):
        return obj.bars.all()

This is a very simple example, but I hope it can help you as a starting point. 这是一个非常简单的例子,但我希望它可以帮助你作为一个起点。

EDIT: 编辑:

You can display the associated objects in the edit form as readonly: 您可以在编辑表单中以只读方式显示关联的对象:

readonly_fields = ('get_bars',)
fields = ('name', 'get_bars')

There is a module called django-admin-extend which provides a generic mechanism to define "Bidirectional many to many fields". 有一个名为django-admin-extend的模块,它提供了一个定义“Bidirectional many to many fields”的通用机制。 I'm not sure if it still works, because the last contribution is two years old, bit it should be worth giving it a try. 我不确定它是否仍然有效,因为最后的贡献是两年了,有点值得尝试一下。

This code below can display both Foo and Bar models in many-to-many relationship on the same page in Django Admin:下面这段代码可以在 Django Admin 的同一页面上以多对多关系显示FooBar模型:

class BarInline(admin.TabularInline):
    model = Bar.foos.through

@admin.register(Foo)
class FooAdmin(admin.ModelAdmin):
    inlines = (BarInline,)

Be careful, if using model = Bar instead of model = Bar.foos.through in many-to-many relationship as shown below:请注意,如果在多对多关系中使用model = Bar而不是model = Bar.foos.through ,如下所示:

class BarInline(admin.TabularInline):
    # model = Bar.foos.through
    model = Bar # This will get error

@admin.register(Foo)
class FooAdmin(admin.ModelAdmin):
    inlines = (BarInline,)

You will get the error below:您将收到以下错误:

ERRORS: <class 'xxx.admin.BarInline'>: (admin.E202) 'xxx.Bar' has no ForeignKey to 'xxx.Foo'.错误:<class 'xxx.admin.BarInline'>: (admin.E202) 'xxx.Bar' 没有指向 'xxx.Foo' 的外键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM