Django detailview get_queryset 和 get_object

标签 django django-generic-views

我正在使用 Django 细节 View 。最初,我使用了 URL 模式

url(r'^todo/details/(?P<pk>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'),

我的观点是
class todoDetailView(DetailView):
model = models.todo

它工作得很好。

在第二种情况下,我的网址是
url(r'^todo/details/(?P<id>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'),

这一次,我修改了我的观点
class todoDetailView(DetailView):
model = models.todo
# context_object_name = 'todo_detail'

 def get_object(self, **kwargs):
    print(kwargs)
    return models.todo.objects.get(id=self.kwargs['id'])

它工作正常,我将第二个案例修改为
class todoDetailView(DetailView):
model = models.todo
# context_object_name = 'todo_detail'

def get_queryset(self):
    return models.todo.objects.get(id=self.kwargs['id'])

然后我得到一个错误,

Generic detail view todoDetailView must be called with either an object pk or a slug.



我知道没有提供适当的 slug 或 pk。所以,最初我添加了 get_object() (它起作用了)但 get_queryset() 不起作用。他们的工作有什么区别??

而且,如果用户仅根据 slug 获取详细信息,我会在 StackOverflow 上阅读

这可以使用
slug_field = 'param_name'
slug_url_kwarg = 'param_name'

链接 - Generic detail view ProfileView must be called with either an object pk or a slug

谁能解释一下 get_object() 和 get_queryset() 的实际工作(如果可能,还可以解释一下 get_slug_field())

随着条款 slug_fieldslug_url_kwarg
提前致谢

最佳答案

get_object返回一个对象(模型的一个实例),而 get_queryset返回一个 QuerySet 对象映射到您的模型的一组可能的多个实例。在 DetailView 的情况下(或者实际上任何继承自 SingleObjectMixin 的类, get_queryset 的目的是 restrict the set of objects from which you'll try to fetch your instance

如果你想显示一个实例的详细信息,你必须以某种方式告诉 Django 如何获取该实例。默认情况下,如错误消息所示,Django 调用 get_object寻找 pk 的方法或 slug URL 中的参数。在你的第一个例子中,你有 pk在 URL 中,Django 设法自动获取您的实例,因此一切正常。在您的第二个示例中,您覆盖了 get_object方法并手动使用 id作为参数传递以获取对象,这也有效。但是,在第三个示例中,您没有提供 get_object方法,所以 Django 执行了默认的方法。 SingleObjectMixin 的默认值 get_object方法没有找到 pk 或 slug,所以它失败了。

有多种方法可以修复它:

1.使用pk在网址中

最简单的方法是简单地使用您在第一个示例中提供的代码。我不知道你为什么不满意,这很好。如果您不满意,请更详细地解释原因。

2.覆盖get_object
这是您提供的第二个解决方案。这是矫枉过正,因为如果您使用正确的选项正确配置了 View (正如您将在以下替代方案中看到的那样),Django 将负责为您获取对象。

3.提供pk_url_kwarg选项

如果你真的想用id由于某种原因在 URL 中,您可以通过指定 pk_url_kwarg 在您的 View 中指明这一点。选项:

class todoDetailView(DetailView):
    model = models.todo
    pk_url_kwarg = 'id'

4.提供slug_fieldslug_url_kwarg选项 [不要这样做]

这是一个糟糕的解决方案,因为您实际上并没有使用 slug,而是使用 id,但理论上它应该可以工作。你基本上会“愚弄”Django 使用 id场,好像它是一个蛞蝓。我之所以提到它,是因为您在问题中明确询问了这些选项。
class todoDetailView(DetailView):
    model = models.todo
    slug_field = 'id'
    slug_url_kwarg = 'id'

关于您的 get_queryset方法:在你的例子中,它甚至不会被执行,但在任何情况下它都会被破坏,因为它返回一个单独的对象而不是一个查询集(这就是 objects.get 所做的)。我的猜测是您可能不需要自定义 get_queryset方法。例如,如果您有一个复杂的权限系统,其中不同的用户只能访问 todo 的不同子集,这将非常有用。对象,我认为这不是你的情况。目前,如果您提供此 get_queryset方法,即使其他一切配置正确,你也会得到一个错误。可能是 AttributeError 说 queryset对象没有属性 filter (因为它实际上是一个 todo 对象而不是一个 QuerySet 对象 as Django expects )。

关于Django detailview get_queryset 和 get_object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52551257/

相关文章:

python - 如何覆盖 django rest 框架( DRF )中的 Response 类?

django - 如何将数据添加到 DetailView 中的上下文对象?

python - Django 中基于类的通用 View 的问题

python Django : how to select the index type?

python - 将使用 Reportlab 生成的图像保存在我的 MEDIA 文件夹中(在 Amazon S3 中)

django - 具有反向 FK 的模型妈妈食谱

python - 在 Django 模型类上设置 __new__ 是否安全?

python - 电子邮件不使用 django 1.9 发送

python - 简单的 django 基于类的通用 View : am I doing it right?

django - 将通用 View 中的查询集限制为以 request.user 作为外键的对象