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

如何实现Bootstrap 5+Django表单中单个fieldset提交并跳转

Django + Bootstrap5 多步骤表单:分步提交并跳转

针对你用Bootstrap5和Django开发的4字段集多步骤表单,要实现第一个字段集的「Next」按钮先提交当前数据再跳转的需求,可通过AJAX异步提交+后端验证的方式实现,具体方案如下:


核心思路

  1. 给第一个字段集的「Next」按钮标记专属类,区分普通跳转按钮
  2. 点击该按钮时,先通过AJAX收集并提交当前字段集的表单数据到Django后端视图
  3. 后端验证数据合法性,返回成功/失败响应
  4. 收到成功响应后,再执行原有的字段集切换动画逻辑

代码修改

1. 修改HTML(标记专属按钮)

仅修改第一个字段集的Next按钮,添加next-submit类:

<!-- 第一个fieldset的Next按钮 -->
<input type="button" name="next" class="next next-submit action-button" value="Next Step"/>
<!-- 记得在表单内添加Django CSRF令牌 -->
{% csrf_token %}

2. 修改JavaScript(添加AJAX提交逻辑)

更新原有的JS代码,增加AJAX提交逻辑:

$(document).ready(function(){
    
var current_fs, next_fs, previous_fs; //fieldsets
var opacity;

// 处理带提交功能的Next按钮
$(".next-submit").click(function(){
    var $btn = $(this);
    current_fs = $btn.parent();
    next_fs = current_fs.next();
    
    // 收集当前fieldset的表单数据
    var formData = current_fs.find('input').serialize();
    
    // AJAX提交到Django视图
    $.ajax({
        url: '/submit-account-step/', // Django后端的URL
        type: 'POST',
        data: formData + '&csrfmiddlewaretoken=' + $('input[name=csrfmiddlewaretoken]').val(),
        dataType: 'json',
        beforeSend: function(){
            $btn.prop('disabled', true).val('提交中...');
        },
        success: function(response){
            if(response.status === 'success'){
                // 提交成功,执行跳转逻辑
                $("#progressbar li").eq($("fieldset").index(next_fs)).addClass("active");
                
                next_fs.show(); 
                current_fs.animate({opacity: 0}, {
                    step: function(now) {
                        opacity = 1 - now;
                        current_fs.css({
                            'display': 'none',
                            'position': 'relative'
                        });
                        next_fs.css({'opacity': opacity});
                    }, 
                    duration: 600
                });
            } else {
                // 提交失败,显示错误信息
                alert(response.message || '数据验证失败,请检查输入');
            }
            $btn.prop('disabled', false).val('Next Step');
        },
        error: function(){
            alert('提交失败,请重试');
            $btn.prop('disabled', false).val('Next Step');
        }
    });
});

// 原有普通Next按钮逻辑
$(".next:not(.next-submit)").click(function(){
    current_fs = $(this).parent();
    next_fs = $(this).parent().next();
    
    $("#progressbar li").eq($("fieldset").index(next_fs)).addClass("active");
    
    next_fs.show(); 
    current_fs.animate({opacity: 0}, {
        step: function(now) {
            opacity = 1 - now;
            current_fs.css({
                'display': 'none',
                'position': 'relative'
            });
            next_fs.css({'opacity': opacity});
        }, 
        duration: 600
    });
});

// 原有Previous按钮逻辑
$(".previous").click(function(){
    current_fs = $(this).parent();
    previous_fs = $(this).parent().prev();
    
    $("#progressbar li").eq($("fieldset").index(current_fs)).removeClass("active");
    
    previous_fs.show();
    current_fs.animate({opacity: 0}, {
        step: function(now) {
            opacity = 1 - now;
            current_fs.css({
                'display': 'none',
                'position': 'relative'
            });
            previous_fs.css({'opacity': opacity});
        }, 
        duration: 600
    });
});

$('.radio-group .radio').click(function(){
    $(this).parent().find('.radio').removeClass('selected');
    $(this).addClass('selected');
});

$(".submit").click(function(){
    return false;
})
    
});

3. Django后端配置

视图函数(views.py)

from django.http import JsonResponse
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError

def validate_email(email):
    if User.objects.filter(email=email).exists():
        raise ValidationError("该邮箱已被注册")
    return email

def validate_username(username):
    if User.objects.filter(username=username).exists():
        raise ValidationError("该用户名已被占用")
    return username

def submit_account_step(request):
    if request.method == 'POST':
        try:
            # 获取并验证第一个字段集的数据
            email = request.POST.get('email')
            uname = request.POST.get('uname')
            pwd = request.POST.get('pwd')
            cpwd = request.POST.get('cpwd')
            
            if not all([email, uname, pwd, cpwd]):
                return JsonResponse({'status': 'error', 'message': '请填写所有必填字段'})
            
            if pwd != cpwd:
                return JsonResponse({'status': 'error', 'message': '两次输入的密码不一致'})
            
            # 验证邮箱和用户名唯一性
            validate_email(email)
            validate_username(uname)
            
            # 存入Session,方便后续步骤调用
            request.session['account_data'] = {
                'email': email,
                'username': uname,
                'password': pwd
            }
            
            return JsonResponse({'status': 'success'})
        
        except ValidationError as e:
            return JsonResponse({'status': 'error', 'message': str(e)})
        except Exception as e:
            return JsonResponse({'status': 'error', 'message': '服务器错误'})
    else:
        return JsonResponse({'status': 'error', 'message': '非法请求'})

URL配置(urls.py)

from django.urls import path
from . import views

urlpatterns = [
    # 其他URL...
    path('submit-account-step/', views.submit_account_step, name='submit_account_step'),
]

补充说明

  • 数据存储:第一步提交的数据存入Session后,后续步骤提交时可取出合并,最终创建正式用户
  • 错误提示:可替换示例中的alert为页面内的友好提示,比如在字段集下方插入错误信息元素
  • 安全性:务必保留CSRF令牌,避免跨站请求伪造攻击

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:25:21