2010-11-30 67 views
10

Django admin filter_horizontal設置爲編輯多對多關係提供了一個很好的小部件。但是這是一個特殊的設置,需要一個字段列表,所以它只能在定義ManyToManyField的(管理員)模型上可用;我怎麼能在其他模型(管理員)上獲得相同的小部件,向後讀取關係?如何在Django Admin中訪問ManyToManyField的兩個方向?

我的模型看起來像這樣(隨意忽略User/UserProfile併發症,它的實際使用情況,雖然):

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

我可以得到管理員表單上一個漂亮的小部件的UserProfile

filter_horizontal = ('sites',) 

但無法看到如何獲得管理員的等效Site管理員。

我還可以通過添加內嵌到SiteAdmin得到部分的方式,定義爲:

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

這是迂迴和不方便雖然;對於簡單管理多對多關係來說,小部件根本不是直觀的。

最後,還有一招described here這涉及對Site定義另一個ManyToManyField並確保它指向同一個數據庫表(並通過一些箍跳,因爲Django是不是真的旨在對描述相同的不同車型不同領域數據)。我希望有人能給我更清潔的東西。

回答

7

下面是一個(或多或少)漂亮的解決方案,這要歸功於http://blog.abiss.gr/mgogoulos/entry/many_to_many_relationships_and並與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_horizontal設置採取一個Django的bug修復,但硬編碼到表格。

+0

非常感謝! :-D – Neal 2013-01-24 19:28:18

相關問題