Детальный просмотр и устаревшие элементы не работают в Django - PullRequest
1 голос
/ 26 сентября 2019

Я работаю над простым приложением, в котором элементы должны истекать автоматически через 5 минут.

В models.py у меня есть следующее:

from django.utils import timezone

def calc_default_expire():
    return timezone.now() + timezone.timedelta(minutes=5)

class MyModel(models.Model):
    uploaded_at = models.DateTimeField(auto_now_add=True)
    expire_date = models.DateTimeField(default=calc_default_expire)
    ...

В моем views.py, У меня есть следующее:

from django.views.generic import DetailView
from .models import MyModel
from django.utils import timezone


class MyModelDetail(DetailView):
    model = MyModel
    queryset = MyModel.objects.filter(expire_date__gt=timezone.now())

У меня странное поведение.Даже через 5 минут, когда я вызываю URL элемента с истекшим сроком действия, он все равно возвращается (http code 200).

Однако, когда я перезагружаю встроенный сервер разработчика django и снова вызываю URL, я 'я получаю 404, что является желаемым результатом.

Я вижу две возможные причины:

  • встроенный веб-сервер кеширует некоторые вещи (сомневаюсь, если честно, яне смог найти ничего в документах, где упоминается такое поведение)
  • Я что-то не так делаю в своем фильтре наборов запросов (но я этого не вижу).

Кажется, что Expire_dateбыть правильно рассчитанным, когда я добавлю новые предметы.Кто-нибудь понял, что мне здесь не хватает?

USE_TZ = True в моем settings.py Кстати.

Ответы [ 2 ]

1 голос
/ 26 сентября 2019

Значение timezone.now() в атрибуте набора запросов вашего представления оценивается во время импорта и никогда не изменяется.

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

class MyModelDetail(DetailView):
    def get_queryset(self): 
        return AppFile.objects.filter(expire_date__gt=timezone.now())

(Обратите внимание, я не понимаю, почему вы определили как модель, так и набор запросов, и еще меньше, почему вы использовали разные модели для каждой; атрибут модели игнорируется, если вы определяетенабор запросов.)

1 голос
/ 26 сентября 2019

Это имеет смысл, поскольку timezone.now() оценивается один раз при запуске сервера.После этого он будет каждый раз запрашивать одно и то же время.

Вместо этого вы можете использовать Now() [Django-doc] , что позволитбаза данных определяет время:

from django.db.models.functions import <b>Now</b>

class MyModelDetail(DetailView):
    model = MyModel
    queryset = MyModel.objects.filter(expire_date__gt=<b>Now()</b>)

Таким образом, оно не будет оценивать время в момент вызова Now(), а будет использовать CURRENT_TIMESTAMP (или некоторую другую функцию, предоставляемую базой данных) каждый раз, когда вы делаете запрос.

Альтернатива - отложить запрос и, таким образом, использовать get_queryset для создания набора запросов каждый раз:

class MyModelDetail(DetailView):
    model = MyModel

    def <b>get_queryset</b>(self):
        return MyModel.objects.filter(expire_date__gt=timezone.now())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...