如何访问Django Admin中的ManyToManyField的两个方向? [英] How to access both directions of ManyToManyField in Django Admin?

查看:145
本文介绍了如何访问Django Admin中的ManyToManyField的两个方向?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Django管理员 filter_horizo​​ntal 设置为编辑多对多关系提供了一个漂亮的小部件。但是这是一个特殊的设置,需要一个字段列表,所以它只能在定义 ManyToManyField 的(admin)模型中使用;如何在其他模型的管理员(管理员)上获得相同的小部件?向后阅读关系?

The Django admin filter_horizontal setting gives a nice widget for editing a many-to-many relation. But it's a special setting that wants a list of fields, so it's only available on the (admin for the) model which defines the ManyToManyField; how can I get the same widget on the (admin for the) other model, reading the relationship backwards?

我的模型看起来像这样(随便忽略用户 / UserProfile 并发症;这是真正的用例):

My models look like this (feel free to ignore the User/UserProfile complication; it's the real use case though):

class Site(models.Model):
    pass
class UserProfile(models.Model):
    user = models.OneToOneField(to=User,unique=True)
    sites = models.ManyToManyField(Site,blank=True)

我可以在 UserProfile 的管理表单上找到一个漂亮的小部件,其中

I can get a nice widget on the admin form for UserProfile with

filter_horizontal = ('sites',)

但看不到如何在网站上获得等价物 admin。

but can't see how to get the equivalent on the Site admin.

我也可以通过在线添加 SiteAdmin ,定义为:

I can also get part-way by adding an inline to SiteAdmin, defined as:

class SiteAccessInline(admin_module.TabularInline):
    model = UserProfile.sites.through

虽然这是迂回和不方便;这个小部件对于简单的管理多对多关系来说并不是直观的。

It's roundabout and unhandy though; the widget is not at all intuitive for simply managing the many-to-many relationship.

最后,有一个技巧这里描述的,其中涉及到定义另一个 ManyToManyField Site ,并确保它指向同一个数据库表(并跳过一些环,因为Django并不是真正设计为在描述相同数据的不同模型上有不同的字段)。我希望有人能给我一些清洁的东西。

Finally, there's a trick described here which involves defining another ManyToManyField on Site and making sure it points to the same database table (and jumping through some hoops because Django isn't really designed to have different fields on different models describing the same data). I'm hoping someone can show me something cleaner.

推荐答案

这是一个(或多或少)整洁的解决方案,感谢 http://blog.abiss.gr/mgogoulos/entry/many_to_many_relationships_and ,并修复了一个Django错误,从< a href =http://code.djangoproject.com/ticket/5247> http://code.djangoproject.com/ticket/5247

Here's a (more or less) tidy solution, thanks to http://blog.abiss.gr/mgogoulos/entry/many_to_many_relationships_and and with a fix for a Django bug taken from http://code.djangoproject.com/ticket/5247

from django.contrib import admin as admin_module

class SiteForm(ModelForm):
    user_profiles = forms.ModelMultipleChoiceField(
        label='Users granted access',
        queryset=UserProfile.objects.all(),
        required=False,
        help_text='Admin users (who can access everything) not listed separately',
        widget=admin_module.widgets.FilteredSelectMultiple('user profiles', False))

class SiteAdmin(admin_module.ModelAdmin):
    fields = ('user_profiles',)

    def save_model(self, request, obj, form, change):
        # save without m2m field (can't save them until obj has id)
        super(SiteAdmin, self).save_model(request, obj, form, change) 
        # if that worked, deal with m2m field
        obj.user_profiles.clear()
        for user_profile in form.cleaned_data['user_profiles']:
             obj.user_profiles.add(user_profile)

    def get_form(self, request, obj=None, **kwargs):
        if obj:
            self.form.base_fields['user_profiles'].initial = [ o.pk for o in obj.userprofile_set.all() ]
        else:
            self.form.base_fields['user_profiles'].initial = []
        return super(SiteAdmin, self).get_form(request, obj, **kwargs)

这使用与 filter_horizo​​ntal 设置相同的窗口小部件,但硬编码到窗体中。

This uses the same widget as the filter_horizontal setting, but hard-coded into the form.

这篇关于如何访问Django Admin中的ManyToManyField的两个方向?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆