Django管理员:list_editable中的ManyToManyField?

时间:2013-03-27 09:35:52

标签: django django-admin many-to-many

在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?

2 个答案:

答案 0 :(得分:2)

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中,您需要覆盖模型admin的方法。如下,

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字段。

注意:如果您打算使用列表中可编辑的多轮多对多ToManyFields,则需要在settings.py中设置DATA_UPLOAD_MAX_NUMBER_FIELDS。

答案 1 :(得分:1)

您可以轻松地向管理网址添加自定义视图,并添加所需的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