【问题标题】:Django: use of __lte for automatic publication of a postDjango:使用 __lte 自动发布帖子
【发布时间】:2020-09-21 02:30:08
【问题描述】:

我正在开发一个博客,我正在使用此过滤器自动将帖子放到网上:

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

此过滤器在本地运行,但不在生产环境中运行。对于从“它将在未来发布”到“它现在在线”的帖子,我必须在生产中重新启动服务器。

为什么会这样?

我可以毫无问题地使用草稿字段更改帖子的状态,无论是在本地还是在生产中。但是如果它被标记为未来的帖子,它似乎不可能自动发布。

根据 Willem Van Onsem 的要求进行编辑

我将此过滤器用于视图和 api 视图。

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)

apiview

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 是一种将 PontField 与博客文章的经典字段(如标题和内容)一起使用的模型。这是一个例子:

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

也许问题出在publishing_date,因为我使用的是timezone.now

【问题讨论】:

  • 您是否每次都“重新运行”查询?还是您在某处定义并重用查询?

标签: django django-views django-filter


【解决方案1】:

您可能只定义了一次查询,然后多次重复使用它。因此,timezone.now没有更新,因此“新”GeoPosts 不会被发布。

但是,您可以通过 Now expression [Django-doc] 来使用数据库时间:

from django.db.models.functions import Now

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

这里Now没有转换成你构造查询集的时间,它使用数据库的时间,所以你可以重用这个查询集。

另一个问题是您使用了全局变量,因此结果会被缓存。这意味着在进行一次查询后,不再进行查询。您可以强制重新查询,例如使用.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)

【讨论】:

  • 可能是我的误会。我认为timezone.now() 类似于Now()。奇怪的是,我只在生产中遇到这个问题。为什么我在 localhost 上开发时没有发生?
  • @MassimilianoMoraca:可能是因为每次您进行更改时服务器都会重新启动。但是不,timezone.now()Now() 并不相似,因为timezone.now() 会产生一个datetime 对象(因此一旦调用,它就会保持相同的值)。
  • 好的,我明白了,谢谢你的解释。我已经使用了您的指示并在 localhost 上运行。下一个未来的帖子将在下周二在线通过,希望一切顺利。有人建议我使用 Celery,但我知道它对于复杂的项目很有用,而且这个博客是一个简单的博客..
  • 很遗憾今天只能在服务器重启后才能看到新帖子
  • @MassimilianoMoraca:但你确实没有使用timezone.now(),对吧?
猜你喜欢
  • 2020-08-07
  • 1970-01-01
  • 2013-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-30
相关资源
最近更新 更多