Django 模型管理器

Django Model Manager

我有一个 Django 模型,用户可以在其中创建对象并将它们保密一段时间。

class MyModel(models.Model):
    creator = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
    private_until = models.DateField(null=True, default=None, blank=True)
    objects = MyModelManager()

在我的 ListView 中,我希望访问者只显示“非私人”对象,而对于经过身份验证的用户,“非私人”对象加上他们自己的私人对象。所以我的经理看起来像这样:

class MyModelManager(models.Manager):
    def include_his_private(self, user):
        if user.is_authenticated:
            include_his_private = super().get_queryset().filter(~Q(private_until__gt=datetime.date.today()))
            include_his_private |= super().get_queryset().filter(Q(creator=user))
            return include_his_private
        else:
            return super().get_queryset().filter(~Q(private_until__gt=datetime.date.today()))

    def get_queryset(self):
        return super().get_queryset().filter(~Q(private_until__gt=datetime.date.today()))

对于我的 ListView 这很好用。但是,当我单击一个对象以获取其 DetailView 时,我在“URL-Level”上收到 404 错误。在我的 URL 中,我有:

    path('<slug:slug>', MyModelDetailView.as_view(), name='mymodel_detail'),

...不知何故,在我有机会让用户进入之前,Django 已经提前检查了每个管理器允许的 slug 的整个 slug。解决我的问题的方法是什么?任何帮助表示赞赏。提前致谢!

编辑: 我的 DetailView 看起来像这样:

class MyModelDetailView(DetailView):
     model = MyModel     
     template_name = 'mymodel_detail.html'      

     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         slug = self.kwargs['slug']
         if self.request.user.is_authenticated:
            obj = MyModel.objects.include_his_private(self.request.user).get(slug=slug)       
         else:
             obj = MyModel.objects.get(slug=slug)

A DetailView [Django-doc] will use the .get_queryset(…) [Django-doc] to obtain a queryset and in the .get_object(…) method [Django-doc],如果路径包含这样的 URL 参数,它将自动过滤 pk and/or slug。因此, 您 运行 get_context_data.

中的自定义逻辑之前完成了此操作

因此您应该覆盖 get_queryset 方法:

class MyModelDetailView(DetailView):
     model = MyModel     
     template_name = 'mymodel_detail.html'

    def <b>get_queryset</b>(self, *args, **kwargs):
        return MyModel.objects.include_his_private(
            self.request.user
        )