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

如何在Django类视图中从HTML表单获取cleaned_data?

问题背景

我有一个使用类视图和手写HTML表单的Django应用,表单代码如下:

<form method="post" action="{% url 'personal-account' %}">
    {% csrf_token %}
    <div class="page slide-page">
      <div class="field">
        <input type="text" placeholder="First name" class="input_1" name="first_name" size="1" value="{{ data.first_name }}">
        <input type="text" placeholder="Last Name" class="input_2" name="last_name" size="1" value="{{ data.last_name }}">
      </div>
      <div class="middle">
        <input type="text" placeholder="Username" class="input_3" name="username" size="1" value="{{ data.username }}">
        <input type="text" placeholder="Email" class="input_6" name="email" size="1" value="{{ data.email }}">
      </div>
      <div class="last">
        <input type="password" placeholder="Password" class="input_4" name="password" size="1" value="{{ data.password }}">
        <input type="password" placeholder="Confirm" class="input_5" name="confirm_password" size="1"  value="{{ data.confirm_password }}">
      </div>
      <div class="field">
        <button type="submit" class="submit-btn">Submit</button>
      </div>
    </div>
</form>

视图代码:

class PersonalSignup(View):
    def post(self, request):
        
        return render(request, 'authentication/personal_signup.html')
    def get(self, request):
        return render(request, 'authentication/personal_signup.html')

现在需要从这些输入框(first_name、last_name等)中获取cleaned_data。


解决方案

因为你用的是手写HTML表单而非Django自带的Form类,有两种方式可以实现类似cleaned_data的清洗后数据获取:

方式一:手动验证清洗数据

直接从request.POST提取原始数据,自行编写验证和清洗逻辑:

修改PersonalSignup视图的post方法:

class PersonalSignup(View):
    def post(self, request):
        # 提取并初步清洗原始数据
        raw_data = {
            'first_name': request.POST.get('first_name', '').strip(),
            'last_name': request.POST.get('last_name', '').strip(),
            'username': request.POST.get('username', '').strip(),
            'email': request.POST.get('email', '').strip(),
            'password': request.POST.get('password', ''),
            'confirm_password': request.POST.get('confirm_password', '')
        }

        cleaned_data = {}
        errors = {}

        # 验证必填字段
        for field in ['first_name', 'last_name', 'username', 'email', 'password', 'confirm_password']:
            if not raw_data[field]:
                errors[field] = "此字段不能为空"
            else:
                cleaned_data[field] = raw_data[field]

        # 验证邮箱格式
        if cleaned_data.get('email'):
            from django.core.validators import validate_email
            from django.core.exceptions import ValidationError
            try:
                validate_email(cleaned_data['email'])
            except ValidationError:
                errors['email'] = "邮箱格式无效"

        # 验证密码一致性
        if cleaned_data.get('password') != cleaned_data.get('confirm_password'):
            errors['password'] = "两次输入的密码不一致"

        # 根据验证结果处理
        if errors:
            return render(request, 'authentication/personal_signup.html', {'data': raw_data, 'errors': errors})
        else:
            # 这里可使用cleaned_data执行后续操作(如创建用户)
            return render(request, 'authentication/personal_signup.html', {'success': True})

    def get(self, request):
        return render(request, 'authentication/personal_signup.html')

模板中可添加错误提示(示例):

<div class="field">
  <input type="text" placeholder="First name" class="input_1" name="first_name" size="1" value="{{ data.first_name }}">
  {% if errors.first_name %}
    <span style="color:red;">{{ errors.first_name }}</span>
  {% endif %}
  <input type="text" placeholder="Last Name" class="input_2" name="last_name" size="1" value="{{ data.last_name }}">
  {% if errors.last_name %}
    <span style="color:red;">{{ errors.last_name }}</span>
  {% endif %}
</div>

方式二:改用Django Form类(推荐)

这是Django的标准实践,自动处理验证和清洗,代码更简洁可靠:

1. 定义Form类

在应用目录下创建forms.py:

from django import forms

class PersonalSignupForm(forms.Form):
    first_name = forms.CharField(max_length=100, required=True)
    last_name = forms.CharField(max_length=100, required=True)
    username = forms.CharField(max_length=150, required=True)
    email = forms.EmailField(required=True)
    password = forms.CharField(widget=forms.PasswordInput, required=True)
    confirm_password = forms.CharField(widget=forms.PasswordInput, required=True)

    # 自定义密码匹配验证
    def clean(self):
        cleaned_data = super().clean()
        password = cleaned_data.get('password')
        confirm_pwd = cleaned_data.get('confirm_password')

        if password and confirm_pwd and password != confirm_pwd:
            raise forms.ValidationError("两次输入的密码不一致")
        return cleaned_data

2. 修改类视图

from .forms import PersonalSignupForm

class PersonalSignup(View):
    def post(self, request):
        form = PersonalSignupForm(request.POST)
        if form.is_valid():
            # 获取自动清洗后的合法数据
            cleaned_data = form.cleaned_data
            # 执行后续操作(如创建用户)
            return render(request, 'authentication/personal_signup.html', {'success': True})
        else:
            # 将含错误的表单传回模板
            return render(request, 'authentication/personal_signup.html', {'form': form})

    def get(self, request):
        form = PersonalSignupForm()
        return render(request, 'authentication/personal_signup.html', {'form': form})

3. 调整模板(可选)

保留手写样式的同时绑定表单数据和错误提示:

<form method="post" action="{% url 'personal-account' %}">
    {% csrf_token %}
    <div class="page slide-page">
      <div class="field">
        <input type="text" placeholder="First name" class="input_1" name="first_name" size="1" value="{{ form.first_name.value|default_if_none:'' }}">
        {% if form.first_name.errors %}
          <span style="color:red;">{{ form.first_name.errors.0 }}</span>
        {% endif %}
        <input type="text" placeholder="Last Name" class="input_2" name="last_name" size="1" value="{{ form.last_name.value|default_if_none:'' }}">
        {% if form.last_name.errors %}
          <span style="color:red;">{{ form.last_name.errors.0 }}</span>
        {% endif %}
      </div>
      <!-- 其他字段按此逻辑调整 -->
      <div class="field">
        <button type="submit" class="submit-btn">Submit</button>
      </div>
    </div>
</form>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 06:24:05