Стратегия поддержания сложных состояний фильтра? - PullRequest
0 голосов
/ 29 августа 2009

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

Примеры фильтров:

field__isnull=True
field__exact="so"
field__field__isnull=False

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

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

Рассмотрим представление с 25 динамически фильтруемыми элементами. Каждый элемент в представлении имеет ссылку, чтобы получить подробный вид элемента. К каждой из этих ссылок добавляется сериализованный объект FilterSpec текущего списка. Таким образом, вы получите огромные URL. Хуже того, один и тот же огромный фильтр добавлен ко всем 25 ссылкам!

Другим вариантом является сохранение FilterSpec в сеансе, но затем вы сталкиваетесь с проблемами, когда удалять FilterSpec. Затем вы обнаружите, что все ваши представления загромождены кодом, пытающимся определить, должен ли фильтр быть удален при подготовке нового списка объектов.

Я уверен, что эта проблема была решена раньше, поэтому я хотел бы услышать другие решения, которые вы, ребята, придумали.

Ответы [ 2 ]

2 голосов
/ 29 августа 2009

Вы определили два варианта для поддержания пользовательского состояния в веб-приложении: сохраняйте его в файлах cookie / сеанс или передавайте по URL-адресам. Я не верю, что третья «серебряная пуля» ждет своего часа, чтобы решить вашу проблему.

Опция строки запроса URL имеет то преимущество, что конкретное состояние просмотра может быть добавлено в закладки, отправлено в виде URL-адреса по электронной почте и т. Д. Это также может сделать ваш код представления немного проще, но за счет некоторого дополнительного кода шаблона, чтобы гарантировать, что правильная строка запроса всегда передается по ссылкам.

Частично ваше предпочтительное решение может зависеть от поведения, которое вы хотите. Например, если пользователь добавляет в закладки (или отправляет электронное письмо другу) URL-адрес для подробного представления элемента, хотите ли вы, чтобы этот URL-адрес просто ссылался на сам элемент или всегда содержал информацию о том, из какого списка вышел этот элемент? из? Если первое, используйте данные сеанса. Если последнее, используйте URL-адреса со строками запроса.

В любом случае, я уверен, что код, который вы находите "загромождающим все ваши взгляды", может быть подвергнут рефакторингу, чтобы быть элегантным, СУХИМ и настолько невидимым, насколько вы хотите. Декораторы и / или представления на основе классов могут помочь.

1 голос
/ 29 августа 2009

В зависимости от того, что вы хотите сделать, вы можете либо создать собственный менеджер , либо добавить новый метод менеджера .

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

from django.db import models
from datetime import datetime

class PublishedPostManager(models.Manager):
    def get_query_set(self):
        return super(PublishedPostManager, self).get_query_set().filter(published=True, time__lt=datetime.now())

class Post(models.Model):
    title = models.CharField(max_length=128)
    body = models.TextField()
    published = models.BooleanField(default=False)
    time = models.DateTimeField()

    objects = models.Manager() # Needed to ensure that the default manager is still available
    published = PublishedPostManager()

Тогда вместо Post.objects.all() вы можете использовать Post.published.all() для извлечения всех записей. Также доступны обычные методы QuerySet:

Post.published.count()
Post.published.select_related().filter(spam__iexact='eggs')
# etc

И, конечно, вы все равно можете использовать менеджер по умолчанию:

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