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

Django如何根据用户输入的会员购买数量动态生成对应个数的表单

代码调整步骤


步骤1:修改forms.py

新增会员数量选择表单,同时调整原有formset配置:

from django import forms
from django.forms import modelformset_factory
from .models import MemberShip

# 新增:会员数量选择表单,限制只能选1/2/5
class MemberCountForm(forms.Form):
    MEMBER_COUNT_CHOICES = [
        (1, '1份'),
        (2, '2份'),
        (5, '5份'),
    ]
    count = forms.ChoiceField(
        choices=MEMBER_COUNT_CHOICES,
        label='您想要购买多少份会员?',
        widget=forms.Select,
        required=True
    )

# 原有formset去掉固定extra参数,后续在视图动态生成
MemberShipFormSet = modelformset_factory(
    MemberShip, 
    fields=("first_name", "last_name", "experience", "date_birth", "gender", "phone"),
    can_delete=False
)

步骤2:修改views.py

新增数量选择页面逻辑,动态根据用户选择的数量生成对应表单:

from django.views.generic import ListView, TemplateView, FormView
from .forms import MemberShipFormSet, MemberCountForm
from .models import MemberShip
from django.urls import reverse_lazy, reverse
from django.shortcuts import redirect

class MemberShipList(ListView):
    model = MemberShip
    template_name = "customer/memberships_list.html"

# 新增:第一步 会员数量选择视图
class MemberCountSelectView(FormView):
    template_name = "customer/member_count_select.html"
    form_class = MemberCountForm

    def form_valid(self, form):
        # 把用户选择的数量存入session,跨请求传递
        self.request.session['member_count'] = int(form.cleaned_data['count'])
        return redirect(reverse('member_ships_add'))

# 调整原有会员信息填写视图
class MemberShipAdd(TemplateView):
    template_name = "customer/memberships_add.html"

    def get(self, *args, **kwargs):
        # 校验用户是否已经选择过数量,未选择则跳回数量选择页
        member_count = self.request.session.get('member_count')
        if not member_count or member_count not in [1,2,5]:
            return redirect(reverse('member_count_select'))
        
        # 动态生成对应数量的表单
        formset = MemberShipFormSet(
            queryset=MemberShip.objects.none(),
            extra=member_count
        )
        return self.render_to_response({'membership_formset': formset})

    def post(self, *args, **kwargs):
        member_count = self.request.session.get('member_count')
        if not member_count or member_count not in [1,2,5]:
            return redirect(reverse('member_count_select'))
        
        formset = MemberShipFormSet(
            data=self.request.POST,
            queryset=MemberShip.objects.none()
        )

        if formset.is_valid():
            formset.save()
            # 提交完成后清空session存储的数量,避免重复使用
            del self.request.session['member_count']
            return redirect(reverse_lazy("member_ships_list"))

        return self.render_to_response({'membership_formset': formset})

步骤3:新增数量选择页面模板 customer/member_count_select.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>选择会员购买数量</title>
</head>
<body>
    <h1>购买会员</h1>
    <form method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">下一步</button>
    </form>
</body>
</html>

步骤4:修改原有会员信息填写模板 customer/memberships_add.html

删除手动新增表单的按钮和对应JS代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>填写会员信息</title>
</head>
<body>
    <h1>填写会员信息</h1>
    <form id="form-container" method="POST">
        {% csrf_token %}
        {{membership_formset.management_form}}
        {% for form in membership_formset %}
            <div class="membership-form">
                <h3>会员{{ forloop.counter }}信息</h3>
                {{form.as_p}}
                <hr>
            </div>
        {% endfor %}
        <button type="submit">提交会员信息并购买</button>        
    </form>
</body>
</html>

步骤5:配置urls.py新增路由

from django.urls import path
from . import views

urlpatterns = [
    path('memberships/', views.MemberShipList.as_view(), name='member_ships_list'),
    # 新增数量选择页路由
    path('select-count/', views.MemberCountSelectView.as_view(), name='member_count_select'),
    path('add-memberships/', views.MemberShipAdd.as_view(), name='member_ships_add'),
]

完成调整后,将站点的「购买会员」按钮指向/select-count/即可符合需求流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 00:36:03