Django视图URL参数异常:UserBook ID显示为Book ID的问题解决
问题分析与解决方案
你的核心问题是视图参数混淆:表单提交时传递的是library.Book的ID,但book_review视图的URL设计期望接收readers.UserBook的ID,导致GET请求(如刷新页面)时因无法找到对应UserBook报错。以下是两种解决方案,可根据需求选择:
方案一:拆分视图(推荐,符合Django单一职责原则)
将「添加图书到个人收藏」和「展示个人图书详情」拆分为两个独立视图,彻底避免参数混淆:
1. 新增添加图书视图
在readers/views.py中添加专门处理添加逻辑的视图:
from django.shortcuts import get_object_or_404, redirect from django.contrib import messages from library.models import Book from .models import UserBook def add_to_my_books(request, book_id): if request.method == 'POST': book = get_object_or_404(Book, pk=book_id) # 检查用户是否已拥有该图书 existing_user_book = UserBook.objects.filter(isbn=book.isbn, owner=request.user).first() if existing_user_book: messages.error(request, "You already have this book in your collection.") return redirect('readers:book_review', user_book_id=existing_user_book.id) else: # 创建新的UserBook user_book = UserBook.objects.create( cover=book.cover, title=book.title, publisher=book.publisher, isbn=book.isbn, nr_pages=book.nr_pages, synopsis=book.synopsis, author=", ".join([author.name for author in book.author.all()]), owner=request.user ) return redirect('readers:book_review', user_book_id=user_book.id) # GET请求直接返回图书详情页 return redirect('library:single_book', id=book_id)
2. 更新URL配置
修改readers/urls.py,新增添加图书的URL:
from django.urls import path from . import views app_name = 'readers' urlpatterns = [ path('add_to_my_books/<int:book_id>/', views.add_to_my_books, name='add_to_my_books'), path('review/my_books/<int:user_book_id>/', views.book_review, name='book_review'), ]
3. 调整表单提交地址
修改图书详情页的表单action,指向新增的视图:
<form action="{% url 'readers:add_to_my_books' book.id %}" method="post"> {% csrf_token %} <button type="submit" class="start-reading-button">Add to My Books</button> </form>
4. 简化原详情视图
让book_review只负责展示个人图书详情:
from django.shortcuts import get_object_or_404, render from .models import UserBook def book_review(request, user_book_id): user_book = get_object_or_404(UserBook, pk=user_book_id, owner=request.user) return render(request, 'readers/book_review.html', {'user_book': user_book})
方案二:修改现有视图(兼容两种场景,维持原有逻辑)
如果不想拆分视图,可修改book_review视图,通过请求方法区分参数类型:
1. 调整视图逻辑
from django.shortcuts import get_object_or_404, redirect, render from django.contrib import messages from library.models import Book from .models import UserBook def book_review(request, item_id): user_book = None if request.method == 'POST': # POST请求:item_id是Book的ID,处理添加逻辑 book = get_object_or_404(Book, pk=item_id) existing_user_book = UserBook.objects.filter(isbn=book.isbn, owner=request.user).first() if existing_user_book: messages.error(request, "You already have this book in your collection.") user_book = existing_user_book else: user_book = UserBook.objects.create( cover=book.cover, title=book.title, publisher=book.publisher, isbn=book.isbn, nr_pages=book.nr_pages, synopsis=book.synopsis, author=", ".join([author.name for author in book.author.all()]), owner=request.user ) # 重定向到正确的UserBook详情页 return redirect('readers:book_review', item_id=user_book.id) else: # GET请求:item_id是UserBook的ID,直接查询展示 user_book = get_object_or_404(UserBook, pk=item_id, owner=request.user) return render(request, 'readers/book_review.html', {'user_book': user_book})
2. 更新URL参数名
修改readers/urls.py中的参数名,使其更通用:
path('review/my_books/<int:item_id>/', views.book_review, name='book_review'),
3. 表单提交地址保持不变
表单仍传递Book的ID,视图会自动处理:
<form action="{% url 'readers:book_review' book.id %}" method="post"> {% csrf_token %} <button type="submit" class="start-reading-button">Add to My Books</button> </form>
内容的提问来源于stack exchange,提问作者RMLemos
相关产品推荐
相关产品推荐

