Фильтр набора запросов диспетчера моделей Django при осведомленном дате и времени: элемент не отображается до перезапуска сервера

У меня есть модель Django, в которой есть поля publish_date и is_published. Я создал менеджер для этой модели, который возвращает все опубликованные элементы, что означает: каждый элемент, у которого is_published=True и publish_date ‹= сейчас.

class PublishedTextManager(models.Manager):
    """
        Filters out all unpublished items and items with a publication date in the future
    """
    def get_query_set(self):
        return super(PublishedTextManager, self).get_query_set() \
            .filter(is_published=True) \
            .filter(publication_date__lte=timezone.now())

Представление, использующее этот менеджер, выглядит так:

class NewsAndEventsOverView(ListView):

    model = News
    queryset = News.published.all().order_by('-publication_date')
    context_object_name = 'news_list'

    def get_context_data(self, **kwargs):
        # Initialize context and fill it with default data from NewsAndEventsOverView super class
        context = super(NewsAndEventsOverView, self).get_context_data(**kwargs)
        # Add view specific context
        context['latest_news_item'] = context['news_list'][0]
        today = timezone.now()
        yesterday = today - timedelta(days=1)
        context['upcoming_events_list'] = Event.published.filter(Q(date_end__gt=yesterday) | Q(date_start__gt=yesterday)).order_by('date_start')
        past_events_list = Event.published.filter(Q(date_end__lt=today) | Q(date_start__lt=today)).order_by('-date_start')
        old_news_list = context['news_list'][1:]
        context['old_news_and_events_list'] = sorted(chain(old_news_list, past_events_list), key=lambda x: x.publication_date, reverse=True)
        return context

Соответствующий urls.py:

from .views import NewsAndEventsOverView

urlpatterns = patterns('',
    # Index page
    url(r'^$', NewsAndEventsOverView.as_view(), name="newsandevents_overview"),
)

Когда я добавляю новость по умолчанию, она получает текущую дату и время (timezone.now()) в качестве даты публикации, однако, когда я обновляю страницу, она не отображается во внешнем интерфейсе, пока я не перезапущу сервер (используя встроенный django -в серверном банкомате). Я нахожусь в амстердамском времени (+2:00), и когда я добавляю 2 часа к фильтру публикации_даты, он работает нормально, поэтому, поскольку я новичок в осведомленности о дате и времени, я предполагаю, что делаю что-то не так. Я пробовал timezone.now с скобками и без них, но это не имеет значения.


person Heyl1    schedule 28.08.2013    source источник
comment
Вы установили часовой пояс в settings.py?   -  person Srinivas Reddy Thatiparthy    schedule 28.08.2013
comment
Спасибо за быстрый ответ. Да, я сделал: TIME_ZONE = 'Европа/Амстердам'. Также: USE_TZ = Истина.   -  person Heyl1    schedule 28.08.2013
comment
Обычно вещи, которые не появляются до перезапуска сервера, вызваны тем, что набор запросов оценивается где-то на уровне модуля. Но вы не показываете никакого кода, который делает это здесь. Не могли бы вы показать хотя бы свой urls.py? Возможно, нам также понадобится увидеть остальную часть фактического вида.   -  person Daniel Roseman    schedule 28.08.2013
comment
Я обновил сообщение, включив в него все представление и соответствующий раздел urls.py.   -  person Heyl1    schedule 28.08.2013
comment
Я также добавлю, что это приложение для проекта django-cms django.   -  person Heyl1    schedule 28.08.2013
comment
Это может быть проблема с кешем, попробуйте установить декоратор @never_cache в своем представлении.   -  person Rohan    schedule 28.08.2013
comment
Поскольку я использую представления на основе классов, я изменил строку urls.py на: url(r'^$', never_cache(NewsAndEventsOverView.as_view()), name="newsandevents_overview"),. Это не сработало.   -  person Heyl1    schedule 28.08.2013
comment
Просто любопытно, нашли ли вы когда-нибудь решение. Я вижу похожую проблему.   -  person Vinod Kurup    schedule 13.10.2013
comment
Нет, к сожалению, нет. Я установил временный хак, как я знаю, a.t.m. серверная часть веб-сайта используется только с GMT+1 (в настоящее время +2 из-за перехода на летнее время), поэтому я только что где-то добавил +2 ко времени, и это исправляет это. Но когда люди из других часовых поясов начнут его использовать, мне нужно будет найти правильное решение. Просто сейчас это не было достаточно важным для меня, чтобы по-настоящему вникать в это.   -  person Heyl1    schedule 14.10.2013


Ответы (2)


Я столкнулся с похожей проблемой, и вот что, по моему мнению, происходит. Когда вы используете атрибут класса queryset, запрос запускается при каждом запросе, но вызов timezone.now() в диспетчере не запускается при каждом запросе, а только при создании экземпляра класса. Вместо этого попробуйте использовать метод get_queryset, который заставляет его запускаться при каждом запросе:

class NewsAndEventsOverView(ListView):

    model = News
    context_object_name = 'news_list'

    def get_queryset(self):
        return News.published.all().order_by('-publication_date')

    ...
person Vinod Kurup    schedule 13.10.2013
comment
Большое спасибо за ваш ответ! Я не заметил, что появился новый ответ, поэтому я так долго не отвечал. Я только что реализовал ваш код, и вы действительно правы, он работает! Я отметил ваш ответ как ответ. Большое спасибо еще раз! - person Heyl1; 08.11.2013

Я на 99% уверен, что у вас на моделях есть что-то подобное:

class News(models.Model):
    ....
    publication_date = models.DateTimeField(default=timezone.now())
    ....

Что это на самом деле делает, так это дает значение аргументу ключевого слова «по умолчанию» вместо передачи функции в качестве объекта, который будет вызываться каждый раз, когда вы создаете новый объект. И вы хотите передать функцию "timezone.now", но не значение этой функции, которое будет "timezone.now()"

Измените его на это:

class News(models.Model):
    ....
    publication_date = models.DateTimeField(default=timezone.now)
    ....

И не забудьте применить это везде в своем коде, где вы хотите указать значение timezone.now по умолчанию для DateTimeField.

Читы! Не забудьте проголосовать, если найдете этот ответ полезным! ;)

person Simanas    schedule 29.08.2013
comment
Спасибо за ваш ответ. Был в отпуске, поэтому не смог ответить. Теперь я могу сообщить, что у меня нет аргумента default в моих DateTimeField. Вместо этого я использую auto_now и auto_now_add. Кроме того, изменение timezone.now() на timezone.now в других местах моего кода не дает никакого эффекта. - person Heyl1; 16.09.2013