2010-06-14 112 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))