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

如何在游戏列表页传递指定ID提交投注值?Django开发问题

解决Django投注应用中传递单个Game ID的问题

首先,你当前的核心问题是没有在表单中传递对应游戏的ID,导致视图无法关联投注到具体游戏。我们先从修复单个游戏表单提交的问题入手,再升级到你想要的「一键批量提交所有投注」的方案。

一、先修复单个游戏的投注提交

1. 模板中添加隐藏字段传递Game ID

在每个游戏的表单里,增加一个隐藏字段来携带当前游戏的ID:

{% for game in games %}
{{ game.id }} | {{ game.home_team }} | {{ game.away_team }} 
<form method="post">
    {% csrf_token %}
    {{ form }}
    <!-- 新增:传递当前游戏的ID -->
    <input type="hidden" name="game_id" value="{{ game.id }}">
    <input type="submit" value="Bet" />
</form>
<br>
{% endfor %}

2. 修改视图代码正确关联游戏

视图里需要从POST中获取这个ID,然后关联到GameBet的gameid字段(注意ForeignKey需要的是Game实例,不是ID列表):

from django.contrib import messages
from .models import Game, GameBet

def game_bet_view(request):
    current_user = request.user  # 假设用户已登录
    if request.method == 'POST':
        form = NewBetForm(request.POST)
        if form.is_valid():
            # 从POST中取出传递的游戏ID
            game_id = request.POST.get('game_id')
            try:
                # 获取对应的Game实例
                target_game = Game.objects.get(id=game_id)
            except Game.DoesNotExist:
                messages.error(request, "无效的游戏ID")
                return redirect('你的游戏列表URL')
            
            bet = form.save(commit=False)
            bet.gameid = target_game  # 赋值Game实例,不是ID列表
            bet.userid = current_user  # 直接赋值User实例更规范,不用写userid_id
            bet.bet = form.cleaned_data.get('bet')  # 用cleaned_data获取验证后的值
            bet.save()
            messages.success(request, "投注成功!")
            return redirect('你的游戏列表URL')
    # GET请求的逻辑...

二、升级为一键批量提交所有投注

如果想实现「一次提交所有游戏的投注」,推荐使用Django的表单集(FormSet),这是官方专门为批量处理同类型表单设计的工具。

1. 在forms.py中定义表单和表单集

from django import forms
from django.forms import formset_factory
from .models import GameBet

class SingleGameBetForm(forms.ModelForm):
    # 把投注选项改成单选按钮,用户体验更好
    bet = forms.ChoiceField(
        choices=[(1, '主胜'), (0, '平局'), (2, '客胜')],
        widget=forms.RadioSelect,
        required=False  # 允许用户跳过某些游戏不投注
    )
    # 隐藏字段存储游戏ID
    game_id = forms.IntegerField(widget=forms.HiddenInput)

    class Meta:
        model = GameBet
        fields = ['bet', 'game_id']

# 创建表单集,extra=0表示不生成额外空表单
GameBetFormSet = formset_factory(SingleGameBetForm, extra=0)

2. 视图中初始化表单集并处理批量提交

from django.shortcuts import render, redirect
from .forms import GameBetFormSet
from .models import Game

def batch_bet_view(request):
    current_user = request.user
    # 获取需要投注的游戏列表
    target_games = Game.objects.all()  # 替换成你的游戏查询逻辑

    if request.method == 'POST':
        formset = GameBetFormSet(request.POST)
        if formset.is_valid():
            for form in formset:
                bet_value = form.cleaned_data.get('bet')
                game_id = form.cleaned_data.get('game_id')
                # 只处理用户选择了投注的游戏
                if bet_value is not None and game_id:
                    try:
                        game = Game.objects.get(id=game_id)
                        # 检查是否已投注,避免重复(可选)
                        existing_bet = GameBet.objects.filter(userid=current_user, gameid=game).first()
                        if existing_bet:
                            existing_bet.bet = bet_value
                            existing_bet.save()
                        else:
                            GameBet.objects.create(
                                userid=current_user,
                                gameid=game,
                                bet=bet_value
                            )
                    except Game.DoesNotExist:
                        messages.error(request, f"ID为{game_id}的游戏不存在")
            messages.success(request, "所有投注已保存!")
            return redirect('batch_bet_view')
    else:
        # 初始化表单集,为每个游戏填充game_id
        initial_data = [{'game_id': game.id} for game in target_games]
        formset = GameBetFormSet(initial=initial_data)

    # 把游戏和对应的表单配对传给模板
    game_form_pairs = zip(target_games, formset)
    return render(request, 'batch_bet_template.html', {
        'game_form_pairs': game_form_pairs,
        'formset': formset
    })

3. 模板中渲染批量表单

<form method="post">
    {% csrf_token %}
    {{ formset.management_form }}  <!-- 表单集必须的管理字段,不能丢 -->
    {% for game, form in game_form_pairs %}
        <div>
            {{ game.id }} | {{ game.home_team }} vs {{ game.away_team }}
            {{ form }}  <!-- 自动渲染投注单选按钮和隐藏的game_id字段 -->
        </div>
        <br>
    {% endfor %}
    <input type="submit" value="一键提交所有投注" />
</form>

关键要点总结

  • 传递单个Game ID的核心是在表单中添加隐藏字段,将{{ game.id }}作为值传递,视图通过request.POST.get()获取
  • ForeignKey字段可以直接赋值模型实例,也可以通过字段名_id直接赋值ID(比如bet.gameid_id = game_id)
  • 批量处理多个表单时,FormSet是最规范的方案,它会自动处理多表单的验证、提交逻辑,避免重复代码

内容的提问来源于stack exchange,提问作者Patr01

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:14:01