Django 管理员:list_editable 中的 ManyToManyField?

Posted

技术标签:

【中文标题】Django 管理员:list_editable 中的 ManyToManyField?【英文标题】:Django admin: ManyToManyField in list_editable? 【发布时间】:2013-03-17 08:11:42 【问题描述】:

在 Django 管理员中,我非常希望能够在列表显示中显示可编辑的 ManyToManyField。

它不一定需要是完整的 ManyToManyField 控件 - 能够只保存一个值对于列表显示的目的就足够了(尽管基础值本质上是多对多的)。

我的模型如下所示:

class Item(models.Model):
    name = models.CharField(max_length=500)
    colour = models.ManyToManyField(Colour, related_name='primary_colour')

如果我在admin.py 试试这个:

class ItemAdmin(admin.ModelAdmin):
    list_display = ('name', 'colour')
    list_editable = ('colour')

然后我得到这个错误:

'ItemAdmin.list_display[6]', 'colour' is a ManyToManyField which is not supported.

是否有任何方式可以在列表显示中显示可编辑的 ManyToManyField 以便快速编辑?

我发现了这个相关的问题,它解释了如何使值在列表显示中可见,但不可编辑:ManyToManyField widget in a django admin change list?

【问题讨论】:

【参考方案1】:

Django 默认不允许在 ModelAdmin 的 list_editable 中添加 ManyToManyField。所以我们需要重写模型管理方法。

在查看您的模型时,您需要按照以下步骤在列表显示页面中获得可编辑的 ManyToManyField。

在apps/forms.py 中,您需要定义哪些ManyToMany 字段需要在列表显示页面中进行编辑。如下,

from django import forms
from app.models import Item


class ItemChangeListForm(forms.ModelForm):

    # here we only need to define the field we want to be editable
    colour = forms.ModelMultipleChoiceField(queryset=Colour.objects.all(), 
        required=False)

在app/admin.py 中,您需要覆盖模型管理员的方法。如下,

from django.contrib import admin
from django.contrib.admin.views.main import ChangeList
from app.models import Item
from app.forms import ItemChangeListForm

class ItemChangeList(ChangeList):

    def __init__(self, request, model, list_display,
        list_display_links, list_filter, date_hierarchy,
        search_fields, list_select_related, list_per_page,
        list_max_show_all, list_editable, model_admin):

        super(ItemChangeList, self).__init__(request, model,
            list_display, list_display_links, list_filter,
            date_hierarchy, search_fields, list_select_related,
            list_per_page, list_max_show_all, list_editable, 
            model_admin)

        # these need to be defined here, and not in ItemAdmin
        self.list_display = ['action_checkbox', 'name', 'colour']
        self.list_display_links = ['name']
        self.list_editable = ['colour']


class ItemAdmin(admin.ModelAdmin):

    def get_changelist(self, request, **kwargs):
        return ItemChangeList

    def get_changelist_form(self, request, **kwargs):
        return ItemChangeListForm


admin.site.register(Item, ItemAdmin)

现在你们都准备好检查更改,运行服务器并检查电影模型的 django admin。您可以直接从列表显示页面编辑 ManyToMany 字段。

注意:如果你打算使用多个ManyToManyFields在列表中可编辑,那么你需要在settings.py中设置DATA_UPLOAD_MAX_NUMBER_FIELDS。

【讨论】:

我有以下错误。你知道为什么吗 ?文件“C:\Users\xxx\Miniconda3\envs\resilisconda2\lib\site-packages\django\contrib\admin\options.py”,第 744 行,在 get_changelist_instance sortable_by 中,TypeError: __init__() 需要 13 个位置参数,但有 14 个被给予。 PyCharm 提示指示:参数“sortable_by”未填充 在 Django2 上效果很好,但在 Django3 上却显示为空表单,哪里有问题?【参考方案2】:

您可以轻松地将自定义视图添加到您的管理 url 并添加所需的 html/javascript/ajax。这是基础知识:

class ItemAdmin(admin.ModelAdmin):
    # regular stuff

    def render_foo(self, obj):
        # add this to your list_display
        html = '<stuff><input/submit action></stuff>'
        return mark_safe(html)

    def get_urls(self):
        urls = super(ItemAdmin, self).get_urls()
        extra_urls = patterns('',
            (r'^process_foo/$', self.admin_site.admin_view(self.process_foo)),
        )
        return extra_urls + urls

    def process_foo(self, request):
        if not request.is_ajax():
            raise Http404
        foo = request.GET.get("attr")
        # process m2m
        # return some json

【讨论】:

谢谢!我想我需要更多的指导:我可以让这个工作正常,但我应该在render_foo 中输入什么?它应该是一个带有选择列表的表单,用户可以在其中选择多种颜色并通过 Ajax 提交给process_foo,是这样的想法吗? 您不需要实际的表单来提交数据,只需使用您需要的任何内容并将数据通过ajax发送到后端,不要忘记验证它。 HTML5 data attributes 是处理数据的一种很好的语义方式,您可以使用 jquery 或原始 javascript onclick 或选择更改来更新属性。

以上是关于Django 管理员:list_editable 中的 ManyToManyField?的主要内容,如果未能解决你的问题,请参考以下文章

django中admin路由系统工作原理

django根据不同用户角色设置数据的访问权限

The value of 'list_editable[0]' refers to the first field in 'list_display' ('ti

在 Django 的管理员上记录活动 - Django

Django,如何将变量从 Django 管理员传递到模板?

Django项目实践4 - Django网站管理(后台管理员)