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
相关产品推荐
相关产品推荐

