Django特定表单提交后禁用其余所有表单的问题修复
问题根因
- 关闭状态判断逻辑倒置且范围错误:商品关闭是全局状态,原代码仅查询当前登录用户是否提交过关停申请,且查到已关停记录时反而标记为未关停
- 最高出价计算逻辑错误:遍历出价记录时对比的是商品初始定价而非单条出价金额,最终得到的
max_bid是数值而非出价对象,无法关联到中标用户 - 关停后清理逻辑不全:仅尝试删除当前用户的收藏记录,未清空所有用户的对应商品收藏,且当前用户未收藏时直接调用
delete()会触发空对象报错 - 模板变量传递缺失:GET请求渲染页面时未传递关停状态、中标人、关停提示等字段,页面刷新后无法识别商品已关停
- 模板语法错误:存在未闭合的form标签,且所有操作表单未加关停状态判断,商品关闭后仍会展示
- POST处理顺序错误:提交关停申请时仍会校验评论、出价表单的合法性,非空校验会直接拦截关停请求
修复代码
views.py 完整修正版
@login_required(login_url='login') def listing(request, id): listing = get_object_or_404(Listings, pk=id) listing_price = listing.bid seller = listing.user comment_obj = Comments.objects.filter(listing=listing) comment_form = CommentForm() bid_form = BidsForm() # 全局判断商品是否关闭,与访问用户无关 closeListing = CloseListing.objects.filter(listing=listing).exists() # 仅商品发布者在商品未关闭时可见关闭按钮 closeListingButton = (seller == request.user) and (not closeListing) # 判断当前用户是否收藏该商品 has_watchlist = WatchList.objects.filter(user=request.user, listing=listing).exists() add_or_remove_watchlist = has_watchlist # 获取所有出价,直接按金额倒序取第一条就是最高出价 bid_obj = Bids.objects.filter(listing=listing).order_by('-bid') max_bid = bid_obj.first() winner = max_bid.user if max_bid else None if request.method == "POST": # 商品已关闭时直接重定向,不处理任何提交操作 if closeListing: return redirect('listing', id=id) comment_form = CommentForm(request.POST) bid_form = BidsForm(request.POST) # 优先处理关闭请求,仅卖家可操作 if request.POST.get('close') and seller == request.user: CloseListing.objects.create(user=request.user, listing=listing) # 删除所有用户对该商品的收藏 WatchList.objects.filter(listing=listing).delete() # 重新查询最高出价 closed_bids = Bids.objects.filter(listing=listing).order_by('-bid') closed_winner = closed_bids.first().user if closed_bids.exists() else None return render(request, "auctions/listing.html",{ "auction_listing": listing, "comments": comment_obj, "bids": bid_obj, "closeListingButton": False, "closeListing": True, "closedMessage": "This listing is closed.", "winner": closed_winner }) # 处理收藏/取消收藏 if request.POST.get('add'): WatchList.objects.get_or_create(user=request.user, listing=listing) add_or_remove_watchlist = True elif request.POST.get('remove'): WatchList.objects.filter(user=request.user, listing=listing).delete() add_or_remove_watchlist = False # 处理评论提交 if comment_form.is_valid(): comment = comment_form.save(commit=False) comment.listing = listing comment.user = request.user comment.save() else: return redirect('listing', id=id) # 处理出价提交 if bid_form.is_valid(): new_bid = bid_form.cleaned_data.get("bid") current_max = bid_obj.first().bid if bid_obj.exists() else 0 if new_bid >= listing_price and new_bid > current_max: bid = bid_form.save(commit=False) bid.listing = listing bid.user = request.user bid.save() else: return render(request, "auctions/listing.html",{ "auction_listing": listing, "form": comment_form, "comments": comment_obj, "bidForm": bid_form, "bids": bid_obj, "watchlist": add_or_remove_watchlist, "closeListingButton": closeListingButton, "closeListing": closeListing, "winner": winner, "message": "Your bid needs to be equal or greater than the listing price and greater than any other bids." }) else: return redirect('listing', id=id) return redirect('listing', id=id) # GET请求渲染时传递所有必要变量 return render(request, "auctions/listing.html",{ "auction_listing": listing, "form": comment_form, "comments": comment_obj, "bidForm": bid_form, "bids": bid_obj, "watchlist": add_or_remove_watchlist, "closeListingButton": closeListingButton, "closeListing": closeListing, "winner": winner, "closedMessage": "This listing is closed." if closeListing else "" })
注意:原代码中sellar为拼写错误,修正为seller,如果你的CloseListing模型关联商品的字段名是listings而非listing,自行对应调整创建记录时的字段名即可。
listing.html 修正版
<!-- 关闭提示 --> {% if closeListing %} <div> {{ closedMessage }} <br> {% if winner %} {{ winner }} has won the auction! {% else %} No valid bids were placed for this listing. {% endif %} </div> {% else %} <!-- 关闭按钮表单,补全闭合标签 --> <form action="{% url 'listing' auction_listing.id %}" method="POST"> {% csrf_token %} {% if closeListingButton %} <input type="submit" value="Close Listing" name="close"> <br><br> {% endif %} </form> <!-- 收藏操作表单 --> {% if watchlist_message %} <div>{{ watchlist_message }}</div> {% endif %} <form action="{% url 'listing' auction_listing.id %}" method="POST"> {% csrf_token %} {% if watchlist %} <input type="submit" value='Remove from Watchlist' name='remove'> {% else %} <input type="submit" value='Add to Watchlist' name='add'> {% endif %} </form> <br> <!-- 出价表单 --> {% if message %} <div>{{ message }}</div> {% endif %} <form action="{% url 'listing' auction_listing.id %}" method="POST" name="newBid"> {% csrf_token %} {{ bidForm }} {{ bidForm.errors }} <input type="submit" value="Place Bid"> </form> <br> {% for bid in bids %} <h6>${{ bid.bid }} <div style="font-family: monospace;">Bid By: {{ bid.user }}</div></h6> {% endfor %} <!-- 评论表单 --> <br> <form action="{% url 'listing' auction_listing.id %}" method="POST"> {% csrf_token %} {{ form }} <input type="submit" value="Add Comment"> </form> {% endif %} <br> <!-- 评论列表始终展示 --> {% for comment in comments %} <h6> {{ comment.comment }} <div style="font-family: monospace;">Comment By: {{ comment.user }}</div></h6> {% endfor %}
修复后效果
- 卖家点击关闭按钮后,商品状态全局标记为已关闭,所有用户访问都能看到关停提示和中标人
- 关闭后自动清空所有用户对该商品的收藏记录
- 关闭后所有操作表单(关闭、收藏、出价、评论)自动隐藏,无法提交任何操作
- 最高出价计算逻辑修正,可正确关联中标用户
- 避免了空对象调用delete的报错,表单重复提交、标签嵌套的问题同步修复
内容的提问来源于stack exchange,提问作者skateb2020
相关产品推荐
相关产品推荐

