如何调整Django中django.contrib.auth与allauth的UserCreationForm字段顺序
问题原因
你遇到的字段顺序无法调整的问题,核心是两个原因:
- 你的自定义表单类和继承的父类重名了,
class UserCreationForm(UserCreationForm)相当于继承自身,继承逻辑会出现异常,需要先给Django原生的UserCreationForm设置别名再继承。 - 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
相关产品推荐
相关产品推荐

