You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 20:27:21