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

Django项目:如何让input标签关联自定义用户模型并保存数据

核心问题排查

你现在的写法有两个硬伤,会直接断掉前后端的数据通路:

  • 前端input的name属性和模型字段名完全对不上:现在input写的是name="first_name"、name="last_name",但模型里的对应字段是full_name、sur_name。Django后端完全靠POST请求里的key值匹配表单字段,名称错了根本收不到用户填的内容。
  • 模板渲染逻辑写反了:你现在把{{form.full_name}}直接塞在input标签的闭合位置,这个对象输出的是内存地址之类的无效内容,既不会生成可用的输入结构,也不会回显用户已经填过的内容,还会把页面HTML结构搞乱。
完整实现步骤

1. 编写对应的数据表单(ModelForm)

Django 提供的 ModelForm 可以自动根据你的User模型生成对应字段、内置校验规则,不用手写重复的匹配逻辑。在你的应用目录下新建forms.py,写入以下代码:

from django import forms
from .models import User

class RegisterForm(forms.ModelForm):
    # 注册场景需要的密码字段,属于认证类字段,没有单独放在模型的基础信息里
    password = forms.CharField(widget=forms.PasswordInput, label="登录密码")
    confirm_password = forms.CharField(widget=forms.PasswordInput, label="确认密码")

    class Meta:
        model = User
        # 只开放允许用户填写的字段,绝对不要把staff、admin、time_stamp这类权限/自动生成的字段放到表单里
        fields = [
            'full_name', 'sur_name', 'email', 'choose_subject',
            'father_name', 'father_sur_name', 'mobile_phone_number',
            'father_email', 'fiscal_code', 'address'
        ]

    # 自定义校验规则
    def clean(self):
        cleaned_data = super().clean()
        pwd = cleaned_data.get("password")
        confirm_pwd = cleaned_data.get("confirm_password")
        if pwd != confirm_pwd:
            raise forms.ValidationError("两次输入的密码不一致")

2. 编写视图处理逻辑

视图负责接收前端提交的POST数据,校验合法性后写入数据库,代码逻辑如下:

from django.shortcuts import render, redirect
from .forms import RegisterForm

def register(request):
    if request.method == "POST":
        # 把前端提交的数据传给表单做校验
        form = RegisterForm(request.POST)
        if form.is_valid():
            # 先不直接入库,处理自定义的密码加密逻辑
            user = form.save(commit=False)
            # 必须对密码做哈希加密,不能存明文
            user.set_password(form.cleaned_data["password"])
            # 给权限字段设默认值,防止用户篡改请求提权
            user.staff = False
            user.admin = False
            user.save()
            # 注册成功后跳转登录页
            return redirect("login")
    else:
        # GET请求时生成空表单传给模板
        form = RegisterForm()
    return render(request, "register.html", {"form": form})

3. 修正前端模板的input标签

你现有模板的样式逻辑可以完全保留,只需要修正input的属性匹配逻辑即可,两个常见实现方式:

  • 如果手写input结构:必须保证name属性和模型字段名完全一致,比如full_name对应的input,name就写name="full_name",sur_name对应的input就写name="sur_name",不能自己随便起名字。
  • 如果想复用Django表单的自动校验、值回显能力,可以直接用表单对象的属性绑定input,修正后的代码示例:
<!-- 姓名输入框 -->
<div class="input-group">
    <label class="label">Full name</label>
    <input 
        class="input--style-4" 
        type="text" 
        name="{{ form.full_name.name }}" 
        value="{{ form.full_name.value|default:'' }}"
    >
    <!-- 表单校验报错信息会自动在这里显示 -->
    {{ form.full_name.errors }}
</div>

<!-- 姓氏输入框 -->
<div class="input-group">
    <label class="label">Sur name</label>
    <input 
        class="input--style-4" 
        type="text" 
        name="{{ form.sur_name.name }}" 
        value="{{ form.sur_name.value|default:'' }}"
    >
    {{ form.sur_name.errors }}
</div>
额外注意事项
  • 模型里的mobile_phone_number定义为IntegerField很容易出问题:用户输入带横杠、空格的手机号格式时会直接校验不通过,建议改成CharField加正则格式校验。
  • 所有带unique=True约束的字段(email、father_email),ModelForm会自动校验重复值的报错信息,不需要手写重复逻辑。
  • 因为你用的是自定义继承AbstractBaseUser的用户模型,绝对不能直接把用户输入的明文密码存进库,必须调用set_password方法做哈希加密,不然后续登录环节会一直校验失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 21:45:08