Администратор Django, фильтрует объекты по ссылке ManyToMany - PullRequest
1 голос
/ 14 июня 2010

Есть приложение для обработки фотографий, простая фотогалерея для django, реализация объектов Photo и Gallery.Объект Gallery имеет поле ManyToMany, которое ссылается на объекты Photo.

Мне необходимо получить список всех фотографий для данной галереи.Можно ли добавить фильтр галереи на страницу администрирования фотографии?Если это возможно, как это сделать лучше всего?

Ответы [ 4 ]

2 голосов
/ 14 июня 2010

Вам нужно написать собственный FilterSpec! Пользовательский фильтр в Django Admin на Django 1.3 или ниже
Это будет выглядеть так:

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 Регистрируется последняя строкаFilterSpec для всех полей, которые имеют отношение к модели галереи.Это не будет работать, как вы упомянули, если поле определено в модели галереи, так как django.contrib.admin.views.main.ChangeList.get_filters проверяет, действительно ли поле, определенное вами в списке, существует в модели (также не работает для related_name).Я думаю, что самый простой способ - это создать собственный шаблон для этого списка изменений и жестко закодировать там свой фильтр, сам FilterSpec не нужен для самой фильтрации, для этого django использует только параметры URL-адреса get!

0 голосов
/ 13 января 2012

@ Джох Демпси указал, что, возможно, вам не нужен специальный FilterSpec только для полей m2m.

Однако сегодня я обнаружил, что хочу один для поля тега django-taggit . Тэги в основном являются отношением m2m, но он жалуется на 'TaggableManager' object has no attribute 'get_choices', если вы попытаетесь добавить поле тега в list_filter.

В данном случае это был код @ 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))
0 голосов
/ 14 марта 2011

Для дальнейшего использования другими пользователями, если у вас есть отношения, они двунаправленные, поэтому вы можете получать фотографии для галерей или галереи для фотографий через ModelAdmin.

Допустим, у вас есть список изменений для вашей модели фотографий:

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

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

admin.site.register(Photo, PhotoAdmin)

Тогда в админе вы увидите фильтр, показывающий все галереи, и если вы нажмете одну, он отфильтрует список, чтобы показать вам только фотографии для этой галереи.

Конечно, это может быть непрактично, если есть МНОГО галерей, но вы можете сделать это, просто используя хорошо документированный ModelAdmin, а не взламывая вместе шаблон или спецификацию фильтров.

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

0 голосов
/ 16 июня 2010

Ну, вот как я это сделал.

Я сделал пользовательский шаблон администратора "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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...