django - Django 类视图 - MultipleObjectsReturned 错误
问题描述
我还是 django 的新手,所以请多多包涵。我正在尝试建立一个关于书籍的网站。现在我有这样的错误
MultipleObjectsReturned at /premium/1/ get() 返回了不止一本书——它返回了 2!
我不知道在哪里寻找错误。这是我的示例代码。
class PageDetailView(LoginRequiredMixin, generic.View):
def get(self, request, *args, **kwargs):
book = get_object_or_404(Book)
page = get_object_or_404(Page)
user_membership = get_object_or_404(Customer, user=request.user)
user_membership_type = user_membership.membership.membership_type
user_allowed = book.allowedMembership.all()
context = {'object': None}
if user_allowed.filter(membership_type=user_membership_type).exists():
context = {'object': page}
return render(request, "catalog/page_detail.html", context)
追溯:
内部 34 中的文件“C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\exception.py”。 response = get_response(request)
_get_response 126 中的文件“C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\base.py”。response = self.process_exception_by_middleware(e, request )
_get_response 124 中的文件“C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\base.py”。 response = Wrapped_callback(request, *callback_args, **callback_kwargs)
视图 68 中的文件“C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\views\generic\base.py”。 return self.dispatch(request, *args , **kwargs)
文件 "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\contrib\auth\mixins.py" 在 dispatch 52. return super().dispatch(request, *args, **kwargs)
调度 88 中的文件“C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\views\generic\base.py”。返回处理程序(请求,*args,* *夸格斯)
获取 127 中的文件“C:\Users\admin\thesis\blackink_website\catalog\views.py”。book = get_object_or_404(Book)
get_object_or_404 中的文件“C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\shortcuts.py” 93. return queryset.get(*args, **kwargs)
获取 403 中的文件“C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\db\models\query.py”。(self.model._meta.object_name,数)
异常类型:MultipleObjectsReturned at /premium/1/ 异常值:get() 返回了不止一本书——它返回了 2!
如果信息不够,我会更新帖子。提前致谢。
更新
这是我的models.py
class Book(models.Model):
title = models.CharField(max_length=200) #i deleted some info to make it shorter
allowedMembership = models.ManyToManyField(Membership, blank=True)
def get_absolute_url(self):
return reverse('book-detail', args=[str(self.id)])
def __str__(self):
return self.title
@property
def pages(self):
return self.page_set.all()
class Page(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE, null=True)
file = models.FileField(upload_to='book_content', validators=[pdf_file_extension], help_text="PDF File Only")
timestamp = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.book.title
def get_absolute_url(self):
return reverse('page-detail', args=[str(self.id)])
page_detail.html
{% if user_membership and user_membership.user == request.user %}
{% for content in book.pages %}
<a href="{{ content.get_absolute_url }}" class="site-btn">Read</a>
{% endfor %}
{% else %}
<button class="site-btn" disabled="disabled">VIP</button>
{% endif %}
解决方案
如果只需要一个对象,但返回多个对象,则查询会引发MultipleObjectsReturned异常。此异常的基本版本在django.core.exceptions中提供;每个模型类都包含一个子类版本,可用于识别已返回多个对象的特定对象类型。
我假设您使用的是最新的 Django 版本。通过从最底部切换官方站点,查看基于您自己版本的正确文档。
以下将是您的最佳链接。
https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/#get-object-or-404
https://docs.djangoproject.com/en/2.1/topics/http/views/#the-http404-exception
像这样尝试,我没有测试过,但我相信它会像我之前测试过的那样工作。还要检查上面的文档,这足以解决这个问题。
根据https://docs.djangoproject.com/en/2.1/topics/class-based-...配置您的 url,这样您就可以通过page_id
并且您的 url 模式应该类似于path('pages/<int:page_id>', PageDetailView.as_view())
or re_path("^pages/(?<page_id>\d+)$", PageDetailView. as_view())
。
使用path()、re_path()、url()时要小心,因为它们有自己的风格 + 优势。
更新:
在查看了 Book(父模型)和 Page(子模型)之间的关系后,我将 urlpattern 从path('pages/<int:page_id>/books/<int:book'
topath('pages/<page_id>
和 id 更改为足以获取相关书籍,因为两个模型之间存在ForeignKey关系。
由于您的视图是PageDetailView,因此最好只传递页面的 id 以进行更好的设计,就像其他人建议的那样(您也可以根据要求传递几个 url 参数,但这里我们不需要)。
from django.http import Http404
class PageDetailView(LoginRequiredMixin, generic.View):
def get(self, request, *args, **kwargs):
try:
# page = get_object_or_404(Page)
page_id = self.kwargs["page_id"]
page = Page.objects.get(pk=page_id)
# book = get_object_or_404(Book)
book_id = page.book.pk
book = Book.objects.get(pk=book_id)
# user_membership = get_object_or_404(Customer, user=request.user)
user_membership = Customer.objects.get(user=request.user)
user_membership_type = user_membership.membership.membership_type
user_allowed = book.allowedMembership.all()
context = {'object': None}
if user_allowed.filter(membership_type=user_membership_type).exists():
context = {'object': page}
return render(request, "catalog/page_detail.html", context)
except Book.DoesNotExist:
raise Http404("Book with id {0} does not exist".format(book_id))
except Page.DoesNotExist:
raise Http404("Page with id {0} does not exist".format(page_id))
except Customer.DoesNotExist:
raise Http404("Cutomer does not exist")
except Exception as e:
raise Exception(str(e))
推荐阅读
- flutter - Flutter Firestore 分页使用 StreamBuilder for Chat 应用程序
- jena - Jena 验证基数未找到缺失的属性
- scala - 尝试测试 CoordinatedShutdown 进程,其中我的服务使用生命周期停止挂钩断开与数据库的连接
- swift - API 滥用:尝试在非拥有协调器上序列化存储访问 - 使用 Assets.xcassets
- python - 从 python 序列化为 JSON 枚举
- locust - 如果 Locust v1.5.3 无法更新使用
- advanced-custom-fields - 高级自定义字段的真或假
- python - Impyla - 在不同服务器上获取相同代码的 SASL 错误
- python - Pygame 错误:FileNotFoundError:没有这样的文件或目录。它们已经在同一个文件夹中
- spring-boot - 带有服务原理的 Azure eventthub 的 Spring Cloud Streams 配置