views:

85

answers:

2

Hello!

There's photologue application, simple photo gallery for django, implementing Photo and Gallery objects. Gallery object has ManyToMany field, which references Photo objects.

I need to be able to get list of all Photos for a given Gallery. Is it possible to add Gallery filter to Photo's admin page? If it's possible, how to do it best?

+1  A: 

You need to write a custom FilterSpec! http://stackoverflow.com/questions/991926/custom-filter-in-django-admin
It'll look like this:

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))

Put it in a module filters.py in your app package and import it in you admin.py (it's important to import it, so that the filter becomes registered on the admin site!)

EDIT: "f" is the field instance, in this case models.ManyToManyField The last line registers the FilterSpec for all fields that have a relation to the Gallery model. This will not work as you mentioned if the field is defined on the Gallery model, since django.contrib.admin.views.main.ChangeList.get_filters checks if the field you define in the list really exist on the model (doesnt work for related_name either). I think the easiest way around is that you could make a custom template for that changelist and hardcode your filter in there, the FilterSpec itself isn't need for the filtering itself, django uses just the url get parameters for that!

lazerscience
What is "f" in the code? Is it Photo instance?The code is registering GalleryFilterSpec for some field of Photo model, isn't it? Photo model has no fields that relates Gallery.Thanks for help!
Nick Z
My answer was too long for comment, so see the edit above!
lazerscience
Well, "f" is field. Looks like I should change Gallery and Photo models to be able to filter Photos by Gallery.Example is great anyway. Thanks again
Nick Z
A: 

Well, that's how I've done it.

I made custom admin template "change_list.html". Custom template tag creates a list of all existing galleries. Filtering is made like this:


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 is set with javascript.

Nick Z