2010-06-14 171 views
1

有photologue應用程序,django的簡單照片庫,實現照片和圖庫對象。 圖庫對象具有ManyToMany字段,該字段引用Photo對象。Django管理,通過ManyToMany過濾對象參考

我需要能夠獲得給定圖庫的所有照片列表。是否可以添加圖庫過濾器照片的管理頁面? 如果可能,如何做到最好?

回答

2

您需要編寫一個自定義FilterSpec! Custom Filter in Django Admin on Django 1.3 or below
它會是這樣的:

from django.contrib.admin.filterspecs import RelatedFilterSpec, FilterSpec 
from models import Gallery 

class GalleryFilterSpec(RelatedFilterSpec): 
    def __init__(self, f, request, params, model, model_admin): 
     self.lookup_kwarg = f.name 
     self._lookup_model = f.rel.to 
     self.lookup_val = request.GET.get(self.lookup_kwarg, None) 
     self.user = request.user 
     self.lookup_choices = [(g.pk, g.name) for g in Gallery.objects.all()] 

    def has_output(self): 
     return len(self.lookup_choices) > 1 

    def title(self): 
     return self._lookup_model._meta.verbose_name 

FilterSpec.filter_specs.insert(0, 
     (lambda f: f.rel.to == Gallery, GalleryFilterSpec)) 

把它放在一個模塊filters.py在您的應用程序包,並在您導入admin.py(它導入是非常重要的,以便過濾器變得對管理網站註冊!)

編輯:「f」是字段實例,在這種情況下,models.ManyToManyField最後一行註冊了與Gallery模型有關係的所有字段的FilterSpec。如果字段是在Gallery模型中定義的,那麼這將不起作用,因爲django.contrib.admin.views.main.ChangeList.get_filters會檢查您在列表中定義的字段是否確實存在於模型中(對於related_name也不適用)。我認爲最簡單的方法是,您可以爲該更改列表創建自定義模板並在其中硬編碼過濾器,FilterSpec本身不需要過濾本身,django僅使用url獲取參數!

+0

什麼是代碼中的「f」?它是照片實例嗎? 該代碼註冊GalleryFilterSpec的某些照片模型領域,不是嗎? 照片模型沒有涉及到圖庫的字段。 感謝您的幫助! – 2010-06-14 12:06:20

+0

我的回答太長,以至於無法發表評論,請參閱上面的修改! – 2010-06-14 12:31:46

+0

那麼,「f」是字段。 看起來我應該更改圖庫和照片模型,以便能夠按照圖庫過濾照片。無論如何,示例很棒。再次感謝 – 2010-06-14 12:32:01

0

好吧,我就是這麼做的。

我製作了自定義管理模板「change_list.html」。自定義模板標籤會創建所有現有圖庫的列表。過濾是這樣的:


class PhotoAdmin(admin.ModelAdmin): 
    ... 
    def queryset(self, request): 
     if request.COOKIES.has_key("gallery"): 
      gallery = Gallery.objects.filter(title_slug=request.COOKIES["gallery"]) 
      if len(gallery)>0: 
      return gallery[0].photos.all() 
      return super(PhotoAdmin, self).queryset(request) 
 

Cookie設置爲javascript。

0

爲了將來可供他人查找,如果您有關係是雙向的,那麼您可以通過ModelAdmin獲取照片或相冊的照片。

比方說,你有你的照片模型修改列表視圖:

from django.contrib import admin 
from yourapp.models import Photo 

class PhotoAdmin(admin.ModelAdmin): 
    list_filter = ('galleries',) 

admin.site.register(Photo, PhotoAdmin) 

然後在管理你會看到一個過濾器顯示所有的畫廊,如果你點擊一個它會過濾列表只顯示該畫廊的照片。

當然,如果有很多畫廊,這可能是不實際的,但只需使用記錄良好的ModelAdmin,而不是將模板或filterspec混合在一起即可到達那裏。

http://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-objects

0

@Jough登普西指出,你也許並不需要一個定製的FILTERSPEC只是針對M2M領域。

但今天我發現我想要一個django-taggit標記字段。標籤基本上是一個m2m關係,但如果您嘗試將標記字段添加到list_filter中,它會抱怨'TaggableManager' object has no attribute 'get_choices'

在這種情況下,它是@ lazerscience的代碼來救援......

然而,它反對的Django 1使用時沒有工作。3,需要添加幾條新線,比較我以下的版本:

class TagFilterSpec(RelatedFilterSpec): 
    def __init__(self, f, request, params, model, model_admin, field_path=None): 
     super(RelatedFilterSpec, self).__init__(
      f, request, params, model, model_admin, field_path=field_path) 

     self.lookup_title = f.verbose_name # use field name 
     self.lookup_kwarg = f.name 
     self.lookup_kwarg_isnull = '%s__isnull' % (self.field_path) 
     self._lookup_model = f.rel.to 
     self.lookup_val = request.GET.get(self.lookup_kwarg, None) 
     self.lookup_val_isnull = request.GET.get(
             self.lookup_kwarg_isnull, None) 
     self.user = request.user 
     self.lookup_choices = [(g.pk, g.name) for g in Tag.objects.all()] 

    def has_output(self): 
     return len(self.lookup_choices) > 1 

    def title(self): 
     return self._lookup_model._meta.verbose_name 

FilterSpec.filter_specs.insert(0, 
     (lambda f: f.rel.to == Tag, TagFilterSpec))