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

Django中Form POST请求无法传值至views.py问题求助

问题描述

在Django开发中实现了「完成第一个表单验证后显示第二个表单」的流程,但遇到两个核心问题:

  1. 提交第二个表单(edisplay.html)时,EmailManagement视图获取到的所有字段值均为空,终端打印结果全是空白
  2. 第一个表单存在自动提交的异常情况

相关代码

views.py

@csrf_exempt
def EmailManagement(request):
    if request.method == "POST":
        code = request.POST.get('scode_no', '')
        if code:
            userlogin = EmailDb.objects.all().filter(scode = code)
            scode = ''
            for i in userlogin:
                scode += i.scode
            # print(scode)
            if code == scode:
                sem = EmailDb.objects.all().filter(scode = code)
                idv = ''
                for i in sem:
                    idv += str(i.id)
                print(idv)
                idv = int(idv)
                p = EmailDb.objects.get(id=idv)
                if request.method == 'POST':
                    institution = request.POST.get('institutionf', '')
                    fullname = request.POST.get('fullnamef', '')
                    email = request.POST.get('personalef', '')
                    contact = request.POST.get('contactf', '')
                    position = request.POST.get('positionf', '')
                    uploaded = request.FILES.get('filef', '')
                    print(uploaded)
                    print(fullname)
                    p.institution = institution
                    p.fullname = fullname
                    p.contact = contact
                    p.email = email
                    p.position = position
                    p.uploaddata = uploaded
                    p.save(update_fields=['institution', 'fullname', 'contact', 'email', 'position', 'uploaddata'])
                
                form = pForm()
                return render(request, 'NEC/edisplay.html', {'p': p, 'form': form})
    form = ResultForm()
    return render(request,'NEC/emailmgt.html', {'form': form})

edisplay.html

<form hx-post="email" hx-target="body" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{p.useremail}}here
    {{form.as_p}}
    <input class="form-check-input" type="checkbox" value="" id="invalidCheck" name='checkbox' required>
    <label class="form-check-label" for="invalidCheck">
        Agree to terms and conditions
    </label>
    <br>
    <input class="bg-success text-white mt-1" style="margin-top: 0px;" type="submit" />
</form>

models.py

class EmailDb(models.Model):
    institution = models.CharField(max_length=300, blank=True, null=True)
    fullname = models.CharField(max_length=50, blank=True, null=True)
    contact = models.CharField(max_length=50,blank=True, null=True)
    email = models.CharField(max_length=300, blank=True, null=True)
    position = models.CharField(max_length=100, blank=True, null=True)
    uploaddata = models.FileField(upload_to='appointment_letter', blank=True, null=True)
    useremail = models.CharField(max_length=100, blank=True, null=True)
    userpassword = models.CharField(max_length=100, blank=True, null=True)
    scode = models.CharField(max_length=200, blank=True, null=True)

    def __str__(self):
        return self.scode

pform.py

from django import forms

class pForm(forms.Form):
    institutionf = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Institution Name'}))
    fullnamef = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Full Name'}))
    personalef = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Personal Email'}))
    contactf = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Personal Email'}))
    positionf = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Contact'}))
    filef = forms.FileField()

问题根源与修复方案

核心问题

  1. 视图逻辑嵌套混乱:同一个视图处理两次POST请求(scode验证、用户信息提交),但未做请求类型区分,导致第二次提交时直接进入scode验证分支,无法正确读取第二个表单的字段
  2. 查询逻辑冗余且风险高:通过循环拼接ID的方式获取对象,若存在多条scode匹配数据会报错;直接用get或filter.first()即可
  3. CSRF配置矛盾:视图加了@csrf_exempt但模板里又有{% csrf_token %},可能引发验证冲突
  4. 表单字段标识缺失:第二个表单未传递需更新的对象ID,视图无法定位要修改的数据库条目

修复步骤

1. 重构视图逻辑,区分请求类型

给两个表单添加隐藏字段标识请求类型,让视图明确当前要处理的操作:

def EmailManagement(request):
    if request.method == "POST":
        action = request.POST.get('action', '')
        # 处理第一个表单:验证scode
        if action == 'verify_code':
            code = request.POST.get('scode_no', '').strip()
            if code:
                try:
                    # 直接通过scode获取唯一对象
                    p = EmailDb.objects.get(scode=code)
                    form = pForm()
                    return render(request, 'NEC/edisplay.html', {'p': p, 'form': form})
                except EmailDb.DoesNotExist:
                    # 加入scode无效的错误提示
                    form = ResultForm()
                    return render(request,'NEC/emailmgt.html', {'form': form, 'error': '无效的scode'})
        # 处理第二个表单:提交用户信息
        elif action == 'submit_info':
            obj_id = request.POST.get('obj_id', '')
            if obj_id:
                try:
                    p = EmailDb.objects.get(id=obj_id)
                    # 读取表单数据
                    institution = request.POST.get('institutionf', '').strip()
                    fullname = request.POST.get('fullnamef', '').strip()
                    email = request.POST.get('personalef', '').strip()
                    contact = request.POST.get('contactf', '').strip()
                    position = request.POST.get('positionf', '').strip()
                    uploaded = request.FILES.get('filef')
                    
                    # 更新数据库对象
                    if institution:
                        p.institution = institution
                    if fullname:
                        p.fullname = fullname
                    if email:
                        p.email = email
                    if contact:
                        p.contact = contact
                    if position:
                        p.position = position
                    if uploaded:
                        p.uploaddata = uploaded
                    p.save()
                    
                    # 跳转至成功页面
                    return render(request, 'NEC/submit_success.html')
                except EmailDb.DoesNotExist:
                    return render(request, 'NEC/error.html')
    # GET请求:显示第一个表单
    form = ResultForm()
    return render(request,'NEC/emailmgt.html', {'form': form})
2. 修改第一个表单(emailmgt.html),添加请求标识
<form method="POST" action="{% url 'email_management' %}">
    {% csrf_token %}
    <input type="hidden" name="action" value="verify_code">
    {{ form.as_p }}
    <input type="submit" value="验证scode">
</form>
3. 修改第二个表单(edisplay.html),添加对象ID与请求标识
<form hx-post="{% url 'email_management' %}" hx-target="body" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="hidden" name="action" value="submit_info">
    <input type="hidden" name="obj_id" value="{{ p.id }}">
    
    {{ p.useremail }}
    {{ form.as_p }}
    
    <input class="form-check-input" type="checkbox" value="" id="invalidCheck" name='checkbox' required>
    <label class="form-check-label" for="invalidCheck">
        同意条款和条件
    </label>
    <br>
    <input class="bg-success text-white mt-1" type="submit" value="提交信息" />
</form>
4. 移除@csrf_exempt并修复表单字段错误

删除视图上的@csrf_exempt装饰器,同时修正pform.py中contactf的占位符错误:

from django import forms

class pForm(forms.Form):
    institutionf = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Institution Name'}))
    fullnamef = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Full Name'}))
    personalef = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Personal Email'}))
    contactf = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Contact'}))
    positionf = forms.CharField(label="", help_text="", widget=forms.TextInput(attrs={'placeholder': 'Position'}))
    filef = forms.FileField()

额外优化建议

  • 使用Django ModelForm替代普通Form,自动关联模型字段,减少手动赋值代码
  • 给表单添加字段验证逻辑(如邮箱格式、联系方式格式),提升数据合法性
  • 配置Django媒体文件路径(MEDIA_ROOT/MEDIA_URL),确保文件上传功能正常
  • 给用户添加操作反馈(如成功提示、错误提示),优化交互体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:31:23