Django 模型管理器
Posted
技术标签:
【中文标题】Django 模型管理器【英文标题】:Django Model Manager 【发布时间】:2021-04-05 08:16:42 【问题描述】:我有一个 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 错误。在我的网址中:
path('<slug:slug>', MyModelDetailView.as_view(), name='mymodel_detail'),
...不知何故,在我有机会将用户传递之前,Django 已经提前检查了整个 slug 与每个 Manager 允许的 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)
【问题讨论】:
你的MyModelDetailView
看起来怎么样?
请edit提问。
已编辑原帖,谢谢指点。
【参考方案1】:
DetailView
[Django-doc] 将使用 .get_queryset(…)
[Django-doc] 获取查询集,并且在 .get_object(…)
method [Django-doc] 中,如果路径包含此类 URL 参数,它将自动过滤 pk
和/或 slug
。因此,这是在您运行get_context_data
中的自定义逻辑之前完成的。
因此,您应该重写 get_queryset
方法:
class MyModelDetailView(DetailView):
model = MyModel
template_name = 'mymodel_detail.html'
def get_queryset(self, *args, **kwargs):
return MyModel.objects.include_his_private(
self.request.user
)
【讨论】:
非常感谢!很简单,一旦你看到解决方案:-/我认为“get_QuerySet”只在 ListView 上有意义:-/ @zeus: 好吧,DetailView
基本上只是在此之上构建了额外的逻辑:因此它将使用get_queryset
,然后使用 slug/pk 执行额外的过滤以检索单个对象。所以它永远不会将get_queryset
作为一个集合来处理。以上是关于Django 模型管理器的主要内容,如果未能解决你的问题,请参考以下文章
django的模型类管理器-----------数据库操作的封装