Представления Django list_details сохраняют набор запросов в память (не обновляя)? - PullRequest
3 голосов
/ 07 декабря 2009

У меня есть собственный менеджер моделей, который выглядит так:

class MyManager(models.Manager)
    def get_query_set(self):
        '''Only get items that are 'approved' and have a `pub_date` that is in
        the past.  Ignore the rest.'''
        queryset = super(MyManager, self).get_query_set()
        queryset = queryset.filter(status__in=('a',))
        return queryset.filter(pub_date__lte=datetime.utcnow())

И это работает достаточно хорошо; однако у меня возникла проблема с использованием generic.list_detail представлений Django object_detail и object_list: кажется, что набор запросов загружается только один раз , и из-за этого он не выбирает элементы, которые должны быть потому что, я полагаю, время utcnow() было вызвано только один раз (при первой загрузке).

Я предполагаю, что это преднамеренно и означает повышение производительности - однако это означает, что видео появляется в другом месте на сайте (в местах, где я не в представлении object_detail), прежде чем оно станет доступным в виде object_detail (см. urls.py ниже). Это приводит к 404 с ...

Есть идеи? Или я должен написать свои собственные представления, чтобы избежать этого?

Спасибо!

urls.py

url(r'^video/(?P<object_id>\d+)$', 
    list_detail.object_detail,
    {   'queryset': Video.objects.all(), },
    name='video_detail',
),

Ответы [ 3 ]

4 голосов
/ 07 декабря 2009

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

Решение на самом деле довольно простое и описано в онлайн-документации: Сложная фильтрация с функциями оболочки : просто создайте небольшое настраиваемое представление, которое будет просто вызывать универсальное представление.
На самом деле, я довольно часто использую подобное решение и чувствую себя довольно комфортно.

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

2 голосов
/ 07 декабря 2009

Попробуйте исправить urls.py до:

url(r'^video/(?P<object_id>\d+)$', 
    list_detail.object_detail,
    {   'queryset': Video.objects.all, }, # here's the difference
    name='video_detail',
)

Edit:

Если это не помогло, попробуйте применить аналогичную технику (передавая callable вместо вызова) к filter ():

return queryset.filter(pub_date__lte=datetime.utcnow)
1 голос
/ 25 мая 2010

У меня есть почти идентичный менеджер моделей для Thornomad, и та же проблема с общими представлениями.

Я должен отметить, что ни одно из предложенных выше предложений не работает:

  • выполнение Video.objects.all без скобок выдает ошибку
  • выполнение queryset.filter (pub_date__lte = datetime.utcnow), опять же без скобок, не выдает ошибку, но не решает проблему

Я также попробовал другой способ, который заключается в использовании лямбда-выражения для возврата набора запросов, например:

qs = lambda *x: Video.objects.all()
url(r'^video/(?P<object_id>\d+)$', 
    list_detail.object_detail,
    {   'queryset': qs(), },
    name='video_detail',
),

... это тоже не сработало, и теперь я вижу, что, должно быть, отчаянно думал, что это сработает:)

lazy_qs = lambda *x: lazy(Post.live_objects.all, QuerySet)

blog_posts = {
    'queryset': lazy_qs(),

... тоже не работает (выдает ошибку), поскольку utils.functional.lazy не знает, как правильно преобразовать результат в QuerySet, насколько я могу судить.

Я думаю, что ответ Роберто об обертывании универсального представления - единственный, который поможет.

В документы django следует внести изменения, чтобы указать на ограничения набора запросов, используемого общими представлениями (в настоящее время в документах есть специальное примечание, чтобы сообщить вам, что все будет хорошо!)

...