MaxDragonheart
MaxDragonheart

Reputation: 1300

Django: use of __lte for automatic publication of a post

I'm developing a blog and I'm using this filter for put online the posts automatically:

geopost_filter = GeoPost.objects.filter(draft=False, publishing_date__lte=timezone.now())

This filter run in local but doesn't run in production. For put online the post that pass from "it will be published in future" to "it is now online" I must restart the server in production.

Why happen this?

I can change the post's status using the draft field without problem, both in local than in production. But it seams not possible to publish automatically a post if it is marked as future post.

EDIT after request from Willem Van Onsem

I use this filter into a view and into an api view.

from django.core.paginator import Paginator
from django.db.models.functions import Now
from django.shortcuts import get_object_or_404, redirect, render
from .models import GeoPost, GeoTag

geopost_filter = GeoPost.objects.filter(
    draft=False,
    publishing_date__lte=Now()
)

def geotag_single(request, slug_tag):
    geotag = get_object_or_404(GeoTag, slug_tag=slug_tag)
    geopost_full = geopost_filter.filter(tags=geotag)

    paginator = Paginator(geopost_full, 10)
    page = request.GET.get("pagina")
    geopost_list = paginator.get_page(page)

    context = {
            "tag": geotag,
            "post_list": geopost_list,
            }

    return render(request, 'geoblog/single_tag.html', context)

apiviews

from rest_framework.decorators import api_view
from rest_framework.response import Response
from geoblog.models import GeoPost
from geoblog.views import geopost_filter

@api_view(["GET"])
def geoblogPost_apiview(request):
    if request.method == "GET":
        if request.user.is_staff:
            objects = GeoPost.objects.all()
        else:
            objects = geopost_filter
        serializer = GeoPostSerializer(objects, many=True)
        return Response(serializer.data)

GeoPost is a model that use the PontField together the classical fields of a blog post like title and contents. This is an example:

from django.contrib.gis.db import models
from django.utils import timezone

GeoPost(models.Model):
    geom = models.PointField(
        blank=True,
        null=True,
    )
    publishing_date = models.DateTimeField(
        default=timezone.now,
        )
    title = models.CharField(
        max_length=70,
        unique=True,
    )
    contents = models.TextField()
    draft = models.BooleanField()

Maybe the problem is in publishing_date because I use timezone.now?

Upvotes: 1

Views: 311

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477503

Likely you defined the query once, and reuse it multiple times. As a result the timezone.now is not updated, and thus the "new" GeoPosts do not get published.

You can however make use of the database time with a Now expression [Django-doc]:

from django.db.models.functions import Now

geopost_filter = GeoPost.objects.filter(
    draft=False, publishing_date__lte=Now()
)

Here Now is not converted to the time when you construct the queryset, it uses the time at the database, so you can reuse this queryset.

Another problem is that you make use of a global variable, and thus the results get cached. This means that after making one query, the query is not done again. You can force requerying, for example with .all():

@api_view(["GET"])
def geoblogPost_apiview(request):
    if request.method == "GET":
        if request.user.is_staff:
            objects = GeoPost.objects.all()
        else:
            objects = geopost_filter.all()
        serializer = GeoPostSerializer(objects, many=True)
        return Response(serializer.data)

Upvotes: 2

Related Questions