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

Django会话无法保存表单数据问题求助

问题描述

开发了一个分阶段Django视图,要求不使用AJAX且保持URL不变,流程为表单获取数据→处理→存入数据库。部分数据无法通过POST传递,尝试存入session但失效:表单POST数据正常,但session存/读要么返回空值要么触发KeyError。手动设置request.session['newvar'] = "test works"可正常读取,说明session功能本身无问题。


视图代码

def processpayment(request, *args, **kwargs):
    if request.method == 'POST':
        form = paymentDetailsForm(request.POST)
        amount = request.POST.get('amount', False);
        stage = request.POST.get('stage', False);  
        if (stage == "checkout"):    
            return render(request, "payment.html", {'form': form, 'amount': amount, 'stage': stage})        
            
        if (stage == "complete"):
            return render(request, "payment.html", {'amount': request.session['amount'], 'stage': stage, 'name': request.session['name']}) 
            
        if (amount == "custom"):
            if form.is_valid():
                amount = form_data.get('amount')
                name = form_data.get('name')
                request.session['amount'] = amount
                request.session['name'] = name
                request.session.modified = True
            return render(request, "payment.html", {'form': form, 'stage': stage, 'amount': amount})  
        return render(request, "payment.html", {'amount': amount, 'stage': stage})                  

    else:       
         return render(request, "payment.html")      
    return render(request, "payment.html")

模板代码

{% load static %}
{% load widget_tweaks %}

<html>

<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/css/bootstrap.min.css" integrity="sha512-rt/SrQ4UNIaGfDyEXZtNcyWvQeOq0QLygHluFQcSjaGB04IxWhal71tKuzP6K8eYXYB6vJV4pHkXcmFGGQ1/0w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>

<body>

<div class="m-3">

{% if stage == "complete" %}  

<<h2 class="mx-auto text-center mb-3">Name:<b>&nbsp; {{ name }}</h2>  

{% elif stage == "checkout" %}

<div style="margin-left: 20%; margin-right: 20%;">

    <h2 class="mx-auto text-center mb-3">Amount to be charged: ${{ amount }}</h2>  

    <div class="col-md-12 mx-auto d-flex justify-content-center mt-2">   
        <div class="container">
                <div class="row ">
                <div class="col-md-6 p-3">
                    <form id='formName' name='formName' action="{% url 'processpayment' %}" method="POST">
                    <input type="hidden" id="amount" name="amount" value="{{ amount }}">
                    <input type="hidden" id="stage" name="stage" value="complete">
                    <button type="submit" name="submit" class="btn btn-primary mt-3">Next</button>
                    </form>
                </div>
            </div>
        </div>    
    </div>

</div>

{% elif amount  == "custom" %}
    
<form action="{% url 'processpayment' %}" method="POST">    
    
    <div class="container pt-3 pb-3">  
          
        <input type="hidden" id="stage" name="stage" value="checkout">         

          <div class="row">
            <div class="col-md-6 mb-2">
              {% render_field form.amount class+="form-control" placeholder="AMOUNT" %}
              </div>
   
            <div class="col-md-6 mb-2">
            {% render_field form.name class+="form-control" placeholder="NAME" %} 
            </div>
            </div>   
          
           <div class="row justify-content-center">
             <span class="input-group-btn">
               <button class="btn btn-primary mt-3" type="submit">Next</button>
             </span>
           </div>        
      </div>

</form>

{% else %}

    <div class="col-md-12 mx-auto d-flex justify-content-center mt-2">   
      <div class="container">
      <div class="row ">
        <div class="col-md-12 text-center p-3">
        <form id='formName' name='formName' action="{% url 'processpayment' %}" method="POST">
        <input type="hidden" id="amount" name="amount" value="custom">
        <button type="submit" name="submit" class="btn btn-primary">Make a payment</button>
        </form>
        </div>
      </div>
      </div>    
    </div>
    
    
{% endif %}
    
</div>

</body>
    
</html>

forms.py代码

from django import forms
from django.forms import widgets
from .models import PaymentMade

class paymentDetailsForm(forms.ModelForm):
    name = forms.CharField(max_length=50)
    amount = forms.IntegerField()

    def __init__(self, *args, **kwargs):
        super(paymentDetailsForm, self).__init__(*args, **kwargs)
        self.fields['name'].required = False
        self.fields['amount'].required = False

    class Meta:
        model = PaymentMade
        fields = ('name', 'amount')

Session配置(settings.py)

SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_COOKIE_AGE = 1200 
SESSION_SAVE_EVERY_REQUEST = True

问题原因及修复方案

核心问题:未定义form_data变量

在视图的amount == "custom"分支中,代码使用了form_data.get('amount'),但form_data从未被定义,正确的做法是使用form.cleaned_data获取验证后的表单数据。

修复后的视图代码

def processpayment(request, *args, **kwargs):
    if request.method == 'POST':
        form = paymentDetailsForm(request.POST)
        amount = request.POST.get('amount', False)
        stage = request.POST.get('stage', False)  
        if stage == "checkout":    
            return render(request, "payment.html", {'form': form, 'amount': amount, 'stage': stage})        
            
        if stage == "complete":
            # 用get方法避免KeyError,提供默认值
            session_amount = request.session.get('amount', 0)
            session_name = request.session.get('name', 'Unknown')
            return render(request, "payment.html", {'amount': session_amount, 'stage': stage, 'name': session_name}) 
            
        if amount == "custom":
            if form.is_valid():
                # 替换form_data为form.cleaned_data
                amount = form.cleaned_data.get('amount')
                name = form.cleaned_data.get('name')
                request.session['amount'] = amount
                request.session['name'] = name
                # Django修改session字典后会自动标记为modified,此行可省略
                # request.session.modified = True
            return render(request, "payment.html", {'form': form, 'stage': stage, 'amount': amount})  
        return render(request, "payment.html", {'amount': amount, 'stage': stage})                  

    else:       
         return render(request, "payment.html")      
    return render(request, "payment.html")

额外优化建议

  1. 读取session时使用get方法并设置默认值,避免KeyError导致页面崩溃
  2. 模板中stage == "complete"分支存在多余的<符号:<<h2,需修正为<h2
  3. 所有POST表单缺少{% csrf_token %}标签,Django默认要求该令牌验证,否则会返回403错误,需在每个表单内添加

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:39:56