扩展CreatesUserForm并保留l10n / i18n内置功能

时间:2018-09-25 09:54:38

标签: python django forms localization internationalization

我正在发现 Django v2.1.1),并希望建立一个登录页面,如果两个字段相同,则其中有2个电子邮件字段,我叫form.is_valid()

项目树

├── manage.py
├── requirements.txt
├── project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── views.py
│   ├── wsgi.py
│   └── templates
│       ├── base.html
│       ├── project
│       │   └── home.html
│       └── registration
│           ├── logged_out.html
│           ├── login.html
│           └── signin.html
└── app
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── urls.py
    ├── views.py
    ├── migrations
    └── templates
        └── app
            └── home.html

project/settings.py中的国际化配置:

# (…)
# Internationalization
LANGUAGE_CODE = 'fr-fr'
USE_I18N = True
USE_L10N = True
# (…)

具有 django基本登录视图,它效果很好

project/views.py

from django.shortcuts import render, redirect
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm

def index(request):
    return render(request, 'project/home.html', {'context':'project index'})

def signin(request):
    # (…)
    form = UserCreationForm()
    return render(request, 'registration/signin.html', {'form': form})

我有一个很好的法语翻译 HTML表单(submit button除外):

Django basic signin form


让我们以以下形式添加一个email字段,email是一个内置的用户字段(如first_namelast_name),所以我只添加一个新类{ {1}}继承自SignInForm

UserCreationForm

project/forms.py

我更新了from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User class SignInForm(UserCreationForm): class Meta: model = User fields = ('username', 'email', 'password1', 'password2')

project/views.py

有效:添加了一个不错的法语翻译字段,但它没有# (…) from project.forms import SignInForm # (…) def signin(request): # (…) form = SignInForm() return render(request, 'registration/signin.html', {'form': form}) 属性:

Django signin form with additionnal email field


现在我被卡住了……

如果我想将属性help_text设置为'required': True字段(这是必需的,并且我想显示翻译后的email)。我发现的唯一方法是覆盖内置电子邮件字段,但我松了翻译,它没有显示help_text

help_text

enter image description here

如果我添加第二个from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from django import forms class SignInForm(UserCreationForm): email = forms.EmailField(required=True) class Meta: model = User fields = ('username', 'email', 'password1', 'password2') 字段,我希望复制带有email2之类的原始User.email,但是看起来这不是存储电子邮件的好地方。我可以如上所述使用email2 = User.email,但我真的很想利用内置翻译。


这是我的问题

如何将forms.EmailField()字段与内置属性(名称,必填,help_text等)一起使用并获取翻译? (当我有一个答案时,我假设将找到对emailsubmitfirst_name进行同样操作的方法)

我可以复制具有此约束的电子邮件字段吗? (我不想存储第二个字段,只是在调用last_name之前检查一下)

_

1 个答案:

答案 0 :(得分:0)

这里有几件事在玩。

UserCreationForm是一个ModelForm,它从模型派生其字段。在这种情况下,模型是您当前的AUTH_USER_MODEL设置。创建email表单字段后,它将检查模型中相应的email字段,并在其中找到help_text,它被包裹在gettext(或{{ 1}})调用以允许i18n以及任何其他属性正常工作。

如果我正确理解了您的问题,那么您想复制gettext_lazy表单字段以覆盖某些(如果有)属性,并允许您针对原始属性进行验证。尽管Django由于使用metaclasses生成表单类而使它比您尝试的要难一些,但是自1.8版以来,已经有一个公共API可以做到这一点:get_field

以下是您可以执行的操作示例:

email

一些评论:

  • 如果使用class SignInForm(UserCreationForm): def __init__(self, *args, **kwargs): super(SignInForm, self).__init__(*args, **kwargs) email_field = settings.AUTH_USER_MODEL._meta.get_field('email') self.fields['email2'] = email_field.formfield() self.fields['email'].required = True self.fields['email2'].required = True class Meta: model = settings.AUTH_USER_MODEL fields = (...) 而不是settings.AUTH_USER_MODEL,则可以避免在整个代码库中更改对User的引用。
  • User也具有复数形式(请参阅docs)以同时检索多个字段。
  • 通常,对表单(覆盖字段属性等)的任何运行时修改都将在get_field方法中进行,因为这是在Django对元类进行黑魔法处理后您首次获得“真实”表单的地方,请参见__init__ 属性覆盖。
  • 如果您要覆盖可翻译的文本,则必须经过required并了解有关此机制的信息(如果要正确执行)。您当然可以用法语对其进行硬编码。 ;)
  • 编辑:表单验证在gettext触发的validatevalidate_{field}表单方法中进行。您不必在视图中包含此逻辑。

我希望有帮助。