查询集中缺少对象

1 投票
1 回答
784 浏览
提问于 2025-04-18 08:35

我有一个模型:

class Post(models.Model):
    is_active = models.BooleanField()
    created = models.DateTimeField()

还有两个类视图:PostListView 和 PostDetailView。

queryset = Post.objects.filter(is_active=True, created__lt=timezone.now())

在这两种情况下。

问题是:每隔一次的 PostListView 渲染响应中缺少一个帖子实例,具体是 created=datetime.datetime(2014, 5, 29, 13, 40, tzinfo=<UTC>)。而 PostDetailView 每隔一次返回 404 错误(每隔一次的响应都是这样!)。当我在命令行中尝试重现这个错误时,一切正常:

>>> Post.objects.filter(is_active=True, created__lte=timezone.now())
[<Post: 1>, <Post: 2>]
>>> Post.objects.filter(is_active=True, created__lte=timezone.now())
[<Post: 1>, <Post: 2>]
>>> Post.objects.filter(is_active=True, created__lte=timezone.now())
[<Post: 1>, <Post: 2>]
>>> Post.objects.filter(is_active=True, created__lte=timezone.now())
[<Post: 1>, <Post: 2>]

更新

class PostListView(ListView):
    queryset = Post.objects.filter(is_active=True, created__lt=timezone.now())
    context_object_name = 'posts'

    def get_context_data(self, **kwargs):
        context = super(PostListView, self).get_context_data(**kwargs)
        context['recommended'] = self.get_queryset().filter(is_recommended=True)[:5]
        return context


class PostDetailView(DetailView):
    queryset = Post.objects.filter(is_active=True, created__lt=timezone.now())
    context_object_name = 'post'

    def get_context_data(self, **kwargs):
        context = super(PostDetailView, self).get_context_data(**kwargs)
        context['recommended'] = self.get_queryset().filter(is_recommended=True)[:5]
        return context


print self.get_queryset().query
SELECT `blog_post`.`id`, `blog_post`.`title`, `blog_post`.`slug`, `blog_post`.`meta_description`, `blog_post`.`img`, `blog_post`.`announcement`, `blog_post`.`content`, `blog_post`.`author_id`, `blog_post`.`is_innovation`, `blog_post`.`is_recommended`, `blog_post`.`is_active`, `blog_post`.`created` FROM `blog_post` WHERE (`blog_post`.`created` < 2014-06-04 15:02:44  AND `blog_post`.`is_active` = True ) ORDER BY `blog_post`.`created` DESC

打印 Post.objects.filter(is_active=True, created__lt=timezone.now()).query SELECT blog_post.id, blog_post.title, blog_post.slug, blog_post.meta_description, blog_post.img, blog_post.announcement, blog_post.content, blog_post.author_id, blog_post.is_innovation, blog_post.is_recommended, blog_post.is_active, blog_post.created FROM blog_post WHERE (blog_post.created < 2014-06-04 15:11:42 AND blog_post.is_active = True ) ORDER BY blog_post.created DESC

运行环境是 nginx + gunicorn + gevent(Ubuntu 服务器,MySQL)。

1 个回答

2

如果你打算在查询集中使用函数来过滤数据,那就不能把它当作一个属性来设置。你必须重写一下 get_queryset 这个方法。

def get_queryset(self):
    queryset = super(PostListView, self).get_queryset()
    return queryset.filter(is_active=True, created__lt=timezone.now())

原因是因为 timezone.now() 每次调用时,都会返回这个类第一次编译时的时间。你可以试试用 .filter(created__lt=timezone.now) 这种方式,但我自己没有尝试过。

撰写回答