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

如何调整Django中django.contrib.auth与allauth的UserCreationForm字段顺序

问题原因

你遇到的字段顺序无法调整的问题,核心是两个原因:

  1. 你的自定义表单类和继承的父类重名了,class UserCreationForm(UserCreationForm) 相当于继承自身,继承逻辑会出现异常,需要先给Django原生的UserCreationForm设置别名再继承。
  2. Django表单默认按字段在类中定义的先后顺序渲染,你继承的父类已经优先定义了username、password1、password2这类内置字段,你后定义的first_name、last_name自然会排在所有内置字段后面,Meta.fields仅控制展示哪些字段,不控制渲染顺序。

解决方法

直接在自定义表单的__init__方法中指定field_order属性即可,Django会自动按你指定的顺序渲染字段,修改后的完整代码如下:

1. 导入部分调整

from django.contrib.auth.forms import UserCreationForm as BaseUserCreationForm
from django.contrib.auth.models import User
from django import forms
from django.utils.translation import gettext_lazy as _
from django.contrib.auth import password_validation, username_validator
from django.core.exceptions import ValidationError

2. 表单类修改

class UserCreationForm(BaseUserCreationForm):
    # 修正原来的错误写法:update方法返回None,不能直接赋值给error_messages
    error_messages = BaseUserCreationForm.error_messages | {
        "duplicate_username": _("This username has already been taken.")
    }
    first_name = forms.CharField(max_length=12, min_length=4, required=True,
                                widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'First Name'}))
    last_name = forms.CharField(max_length=12, min_length=4, required=True,
                               widget=forms.TextInput(attrs={'class': 'form-control'}))
    email = forms.EmailField(max_length=50, help_text='Required. Inform a valid email address.',
                             widget=forms.TextInput(attrs={'class': 'form-control'}))
    password1 = forms.CharField(label=_('Password'),
                                widget=forms.PasswordInput(attrs={'class': 'form-control'}),
                                help_text=password_validation.password_validators_help_text_html())
    password2 = forms.CharField(label=_('Password Confirmation'), widget=forms.PasswordInput(attrs={'class': 'form-control'}),
                                help_text=_('Just Enter the same password, for confirmation'))
    username = forms.CharField(
        label=_('Username'),
        max_length=150,
        help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[username_validator],
        error_messages={'unique': _("A user with that username already exists.")},
        widget=forms.TextInput(attrs={'class': 'form-control'})
    )

    class Meta(BaseUserCreationForm.Meta):
        model = User
        fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2',)
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 按你想要的渲染顺序填写字段名即可
        self.field_order = ['first_name', 'last_name', 'username', 'email', 'password1', 'password2']
        
        # 如果你使用的Django版本低于2.0,不支持field_order属性,用下面这段代码手动重排即可
        # custom_order = ['first_name', 'last_name', 'username', 'email', 'password1', 'password2']
        # self.fields = {field: self.fields[field] for field in custom_order}

    def clean_username(self):
        username = self.cleaned_data["username"]
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            return username
        raise ValidationError(
            self.error_messages["duplicate_username"]
        )

修改后重启服务即可看到字段顺序按你指定的规则渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:39:04