为啥即使创建了对象,django 也找不到与查询匹配的任何对象
Posted
技术标签:
【中文标题】为啥即使创建了对象,django 也找不到与查询匹配的任何对象【英文标题】:Why is django not finding any object matching the query, even though object is created为什么即使创建了对象,django 也找不到与查询匹配的任何对象 【发布时间】:2021-09-23 01:37:17 【问题描述】:HEADUP:我不知道这是否是重复的。有很多类似的标题之一,但他们没有回答我的问题。但是,如果它是重复的,请通知我。
我有一个名为 Item 的模型:
class Item(models.Model):
title = models.CharField(max_length=120)
date_created = models.DateTimeField(default=timezone.now)
deadline = models.DateTimeField(default=timezone.now() + timedelta(5))
task = models.ForeignKey(Task, on_delete=models.CASCADE)
is_completed = models.BooleanField(default=False)
如果您看到,Item 引用了一个名为 Task 的 ForeignKey:
class Task(models.Model):
title = models.CharField(max_length=120)
description = models.TextField()
date_created = models.DateTimeField(default=timezone.now)
deadline = models.DateTimeField(default=timezone.now() + timedelta(5))
author = models.ForeignKey(User, on_delete=models.CASCADE)
is_completed = models.BooleanField(default=False)
我有一个项目的删除视图:
class DeleteItemView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Item
template_name = 'function/delete_item.html'
success_url = reverse('all-items')
def test_func(self):
item = get_object_or_404(Item, id=self.kwargs['pk2'])
if item.task.author == self.request.user and not item.task.is_completed:
return True
return False
def get_context_data(self, **kwargs):
context = super(DeleteItemView, self).get_context_data(**kwargs)
context['task'] = Task.objects.filter(id=self.kwargs['pk'])[0]
return context
删除视图的 url 模式是:
path('task/<int:pk>/item/<int:pk2>/delete/', DeleteItemView.as_view(), name='delete-item'),
pk
用于 Task 模型,pk2
用于 Item 模型。
现在,我的问题是这样的。每当我尝试转到此删除视图时,都会导致错误,提示找不到与查询匹配的项目 (404)。它说Raised by: function.views.DeleteItemView
。我不知所措,花了将近半天的时间试图弄清楚这一点,但没有成功。
任何帮助或答案将不胜感激。
【问题讨论】:
什么是pk
,什么是pk2
?它们到底适用于哪种型号?此外,您应该在问题中显示您的 url 模式。
我添加了关于什么 pk 和 pk2(任务模型和项目模型)以及 url 模式的描述。感谢您的提示!
【参考方案1】:
这里的问题是缺乏对处理单个对象的基于类的视图的理解。任何处理单个对象的视图都继承自SingleObjectMixin
[Django docs]。 SingleObjectMixin
使用作为关键字参数传递给视图的 pk 或 slug 中的一个(或两者)获取相关对象。
pk 的 kwarg 名称由 pk_url_kwarg
表示,默认为 pk
,(意味着如果有一个 kwarg pk
传递给视图,它将用于获取对象)和 kwarg对于slug
表示为slug_url_kwarg
。
在您看来,您处理 两个 对象,一个是 Item
,另一个是 Task
。通用视图应该处理Item
。这里的问题是您将Item
的pk 传递为pk2
并将Task
的pk 传递为pk
!该视图当然认为pk
是它需要处理的实例,因此您会收到错误。
一种解决方案是交换两个 kwargs 的名称,但我们可以做得更好。 pk
和 pk2
不是很具有描述性,是吗?让我们更改它们的名称以更具描述性。
在您的 url 模式中,更改捕获参数的名称:
path('task/<int:task_pk>/item/<int:item_pk>/delete/', DeleteItemView.as_view(), name='delete-item'),
在您看来,设置 pk_url_kwarg
并更正名称:
class DeleteItemView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Item
template_name = 'function/delete_item.html'
success_url = reverse('all-items')
pk_url_kwarg = 'item_pk' # set this
def test_func(self):
item = get_object_or_404(Item, id=self.kwargs['item_pk'])
if item.task.author == self.request.user and not item.task.is_completed:
return True
return False
def get_context_data(self, **kwargs):
context = super(DeleteItemView, self).get_context_data(**kwargs)
context['task'] = Task.objects.filter(id=self.kwargs['task_pk'])[0]
return context
事实上要注意的一件事是,如果 Task
是与 Item
相关的那个,你甚至不需要 在你的 url 中传递它,你可以简单地写:
task = item.task
【讨论】:
哇哇哇!这非常有帮助,因为您不仅提供了一个很好的解决方案,而且还附上了很好的解释。太感谢了。这让我烦恼了很久。再次感谢!!!!!!以上是关于为啥即使创建了对象,django 也找不到与查询匹配的任何对象的主要内容,如果未能解决你的问题,请参考以下文章
即使已安装,在 Docker 容器中也找不到“json-server”命令