Django detailview获取\u查询集和获取\u对象
我正在使用Django detailview。最初,我使用URL模式Django detailview获取\u查询集和获取\u对象,django,django-generic-views,Django,Django Generic Views,我正在使用Django detailview。最初,我使用URL模式 url(r'^todo/details/(?P<pk>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'), 它工作得很好 在第二种情况下,我的URL是 url(r'^todo/details/(?P<id>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'), 很
url(r'^todo/details/(?P<pk>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'),
它工作得很好
在第二种情况下,我的URL是
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_queryset(self):
return models.todo.objects.get(id=self.kwargs['id'])
然后我得到一个错误
必须使用对象pk或slug调用Generic detail view todetailview
我知道没有提供合适的slug或pk。因此,最初我添加了get_object()(它工作了),但get_queryset()不工作。他们的工作有什么不同
而且,如果用户仅根据slug获取详细信息,我在StackOverflow上读到
这是可以使用的
slug_field = 'param_name'
slug_url_kwarg = 'param_name'
链接-
有人能给我解释一下get_object()和get_queryset()的实际工作情况吗(如果可能的话,也可以是get_slug_field())
与术语slug\u字段
和slug\u url\u kwarg
提前感谢我无法帮助您了解错误消息的明确含义,但是在列表视图中,get多个对象使用了
get\u queryset
,而get\u object
用于获取单个对象(即DetailView
)
如果你有一个pk可以用来获取一个对象,你不需要指定一个slug字段。Slug字段用于在没有或不能公开显示主键时过滤掉对象
get\u object
返回一个对象(模型的实例),而get\u queryset
返回一个queryset对象映射到模型的一组潜在多个实例。对于DetailView
(或者实际上是从SingleObjectMixin
继承的任何类),get\u queryset
的目的是
如果要显示实例的详细信息,您必须以某种方式告诉Django如何获取该实例。默认情况下,正如错误消息所示,Django调用get_object
方法,该方法在URL中查找pk
或slug
参数。在第一个示例中,您在URL中有pk
,Django m管理自动获取实例,因此一切正常。在第二个示例中,您覆盖了get_object
方法,并手动使用作为参数传递的id
来获取对象,这同样有效。但是,在第三个示例中,您没有提供get_object
方法,因此Django执行默认值。SingleObjectMixin的默认get_object
方法未找到pk或slug,因此失败
有多种方法可以解决此问题:
1.在URL中使用pk
最简单的方法是简单地使用您在第一个示例中提供的代码。我不知道您为什么不满意,这很好。如果您不满意,请详细解释原因
2.覆盖get\u对象
这是您提供的第二个解决方案。这太过分了,因为如果您使用正确的选项正确配置视图(如您将在下面的备选方案中看到的),Django将负责为您获取对象
3.提供pk\u url\u kwarg
选项
如果出于某种原因确实想在URL中使用id
,可以通过指定pk\u URL\u kwarg
选项在视图中指明:
class todoDetailView(DetailView):
model = models.todo
pk_url_kwarg = 'id'
4.提供slug\u字段
和slug\u url\u kwarg
选项[不要这样做]
这是一个糟糕的解决方案,因为您实际上并没有使用slug,而是一个id,但在理论上它应该可以工作。您基本上会“愚弄”Django,让它像使用slug一样使用id
字段。我之所以提到它,是因为您在问题中明确询问了这些选项
class todoDetailView(DetailView):
model = models.todo
slug_field = 'id'
slug_url_kwarg = 'id'
关于您的
get\u queryset
方法:在您的示例中,它甚至不需要执行,但在任何情况下它都会被破坏,因为它返回一个单独的对象而不是queryset(这就是objects.get
所做的)。我猜您可能根本不需要自定义的get\u queryset
方法。例如,如果您有一个复杂的权限系统,其中不同的用户只能访问todo
对象的不同子集,这将非常有用,我想这不是您的情况。当前,如果您提供此get\u queryset
方法,则即使其他所有配置都正确,也会出现错误。可能是AttributeError说queryset
对象没有属性filter
(因为它实际上是一个todo
对象,而不是一个queryset对象)
当您重写get_object
时,您正在替换此默认行为,因此不会出现任何错误
当您重写get\u queryset
时,Django首先运行get\u queryset
方法获取查询集。然后,它尝试使用pk
或slug
从该查询集获取对象,您会收到一个错误,因为您没有使用它们
和参数都在文档中定义。slug\u字段
是用于获取项目的模型中字段的名称,slug\u url\u kwarg
是url模式中参数的名称。在您的情况下,您使用主键(pk
/id
)获取对象,因此您不应该使用这两个选项中的任何一个
对于使用
(?p[\d]+)
的URL模式,可以使用pk\u URL\u kwarg='id'
。这将告诉Django使用id
从URL获取对象。但是,使用(?p[\d]+)的第一个URL模式要简单得多
,则不必重写上述任何方法/属性。我无法理解您的问题。这两者之间有什么区别
class todoDetailView(DetailView):
model = models.todo
pk_url_kwarg = 'id'
class todoDetailView(DetailView):
model = models.todo
slug_field = 'id'
slug_url_kwarg = 'id'