Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django seems to be caching datetime.now()

I have a model that looks like this:

class Item(models.Model):
    ...
    publish_date = models.DateTimeField(default=datetime.datetime.now)
    ...

And a manager that looks like this:

from datetime import datetime

class ItemManager(Manager):
    def published(self):
        return self.get_query_set().filter(publish_date__lte=datetime.now()

And a view that looks like this:

class ItemArchive(ArchiveIndexView):
    queryset = Item.objects.published()
    date_field = 'publish_date'

The idea being that I can call Item.objects.published() and get a queryset of all published Items.

The problem is that Django seems to be executing the datetime.now() call in the manager when the server is started and then caching that value. So if today is May 24th, and I created an Item with a publish date of May 23rd, and started the server on May 22nd, that May 23rd item will not show up in the ItemArchive view. As soon as I restart Apache, the May 23rd item shows up in the view correctly.

How can I force Django to execute datetime.now() every time the manager is called?

like image 574
user1272534 Avatar asked May 24 '12 16:05

user1272534


People also ask

Does Django automatically cache?

Unless we explicitly specify another caching method in our settings file, Django defaults to local memory caching. As its name implies, this method stores cached data in RAM on the machine where Django is running. Local memory caching is fast, responsive, and thread-safe.

What is caching in Django?

Django comes with its own caching system that lets you save your dynamic pages, to avoid calculating them again when needed. The good point in Django Cache framework is that you can cache − The output of a specific view. A part of a template. Your entire site.

How do I set the default time in Django?

To enable it, set USE_TZ = True in your settings file. In Django 5.0, time zone support will be enabled by default. Time zone support uses zoneinfo , which is part of the Python standard library from Python 3.9. The backports.


2 Answers

I believe this is caused by your view defining queryset = Item.objects.published() as a class variable. This line will be executed once, when your ItemArchive class is initially imported. You should move that line into a method where it will be executed each time a view is called.

like image 152
dgel Avatar answered Sep 21 '22 22:09

dgel


Don't use the queryset class variable, and override get_queryset instead. In general, I think queryset is a bit of a red herring. If you just specify model instead, Django automatically sets the queryset to self.model.objects.all(). If you need any filtering, 99 times out of 100 you'll need to override get_queryset to be thread-safe. Try the following instead.

class ItemArchive(ArchiveIndexView):
    model = Item
    date_field = 'publish_date'

    def get_queryset(self):
        return super(ItemArchive, self).get_queryset().published()
like image 44
Chris Pratt Avatar answered Sep 19 '22 22:09

Chris Pratt