2

I have a Django model which has a publication_date and an is_published fields. I've created a manager for this model which returns all published items which means: every item that has is_published=True and publication_date <= now.

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())

The view that's using this manager looks like this:

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

Relevant urls.py:

from .views import NewsAndEventsOverView

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

When I add a news item by default it receives the current datetime (timezone.now()) as publication date, however when I refresh the page it doesn't display in the front-end until I do a server restart (using django built-in server a.t.m). I am in Amsterdam time (+2:00) and when I add 2 hours to the publication_date filter it works fine, so since I'm new to datetime awareness I'm guessing I'm doing something wrong. I've tried the timezone.now with and without brackets, but that doesn't make a difference.

Heyl1
  • 2,437
  • 3
  • 24
  • 31
  • Did you set timezone in settings.py? – Srinivas Reddy Thatiparthy Aug 28 '13 at 10:27
  • Thanks for your swift reply. Yes I did: TIME_ZONE = 'Europe/Amsterdam'. Also: USE_TZ = True. – Heyl1 Aug 28 '13 at 10:29
  • 3
    Usually "things not appearing until server restart" is caused by a queryset being evaluated at module level somewhere. But you don't show any code that does this here. Could you show your urls.py at least? We might need to see the rest of the actual view, too. – Daniel Roseman Aug 28 '13 at 10:31
  • I've updated the post to include the entire view and the relevant urls.py section. – Heyl1 Aug 28 '13 at 10:37
  • I'll also add that this is an application for a django-cms django project. – Heyl1 Aug 28 '13 at 10:57
  • It might be cache issue, try setting `@never_cache` decorator on your view. – Rohan Aug 28 '13 at 10:57
  • Because I'm using class based views I changed the urls.py line to: `url(r'^$', never_cache(NewsAndEventsOverView.as_view()), name="newsandevents_overview"),`. This didn't work. – Heyl1 Aug 28 '13 at 11:05
  • Just curious if you ever found a solution. I'm seeing a similar issue. – Vinod Kurup Oct 13 '13 at 00:54
  • Nope, unfortunately I haven't. I've put in a temporary hack as I know a.t.m. the back-end of the website is only ever used from GMT+1 (currently +2 due to daylight savings) so I've just added a +2 to the time somewhere and that fixes it. But when people from other time zones will start using it I will have to find a proper fix. It just wasn't a high enough priority right now for me to really dig into it. – Heyl1 Oct 14 '13 at 06:32

2 Answers2

2

I am 99% sure that you have something like that on your models:

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

What this actually does it gives a value to keyword argument 'default' instead of passing a function as an object, to be called every time you create a new object. And you want to pass a function 'timezone.now' but not a value of this function, wich would be 'timezone.now()'

Change it to this:

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

And do not forget to apply this everywhere on your code where you want to give default timezone.now value to DateTimeField

Cheets! Do not forget to up-vote if you find this answer useful! ;)

Simanas
  • 2,793
  • 22
  • 20
  • Thank you for your reply. I was away on vacation, so was unable to reply. I can now report that I do not have a `default` argument in my `DateTimeField`s. Instead I use `auto_now` and `auto_now_add`. Also, changing `timezone.now()` to `timezone.now` in other places in my code has no effect. – Heyl1 Sep 16 '13 at 07:27
1

I've been running into a similar issue, and here's what I think is going on. When you use the queryset class attribute, the query gets run on each request, but the timezone.now() call within the Manager does not get run on each request, only at class instantiation. Try using the get_queryset method instead, which forces it to be run on each request:

class NewsAndEventsOverView(ListView):

    model = News
    context_object_name = 'news_list'

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

    ...
Vinod Kurup
  • 2,676
  • 1
  • 23
  • 18
  • Thanks very much for your reply! I hadn't noticed a new reply had appeared which is why it has taken me so long to respond. I've just implemented your code and indeed you're right, it works! I've marked your response as the answer. Thanks very much again! – Heyl1 Nov 08 '13 at 15:07