Расширьте CreatesUserForm и оставьте встроенную функцию l10n / i18n - PullRequest
0 голосов
/ 25 сентября 2018

Я обнаруживаю Django (v2.1.1) и хочу настроить страницу входа , в которой у меня есть 2 поля электронных писем, если эти 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_name & last_name), поэтому я просто добавляю новый класс 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})

Это работает : добавлено хорошее французское переведенное поле , но оно не имеет атрибута help_text:

Django signin form with additionnal email field


Теперь я застрял ...

Если я хочу установитьАтрибут 'required': True в поле email (требуется, и я хочу показать переведенный help_text).Единственный способ, который я нашел, это переопределить встроенное поле электронной почты, но я теряю перевод, и он не показывает help_text:

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')

enter image description here

Если я добавлю второе поле email2, я надеялся скопировать оригинал User.email с чем-то вроде email2 = User.email, но похоже, что это не то место, где хранится электронная почта.Я могу использовать forms.EmailField(), как указано выше, но мне бы очень хотелось воспользоваться встроенным переводом.


Тогда вот мои вопросы :

Как использовать поле email с встроенными атрибутами (name, обязательно, help_text,…) и получать переводы?(Когда у меня есть ответ, я предполагаю, что найду способ сделать то же самое с submit, first_name & last_name)

Могу ли я продублировать поле электронной почты с этим ограничением?(Я не хочу сохранять это второе поле, просто проверяю перед вызовом form.is_valid())

_

1 Ответ

0 голосов
/ 27 сентября 2018

Здесь есть несколько вещей:

UserCreationForm - это ModelForm, который получает свое поле из модели.В этом случае модель является вашей текущей настройкой AUTH_USER_MODEL .Когда поле формы email создано, оно проверяет соответствующее поле email из модели, где находит help_text, заключенное в gettext (или gettext_lazy)позвоните, чтобы разрешить i18n работать, а также любой другой атрибут.

Если я правильно понимаю ваш вопрос, вы хотите продублировать поле формы email, чтобы переопределить некоторые (если есть) атрибуты и позволить вамчтобы проверить это против оригинального.В то время как Django делает это немного сложнее, чем вы пытались, потому что он использует метаклассы для генерации класса формы, существует публичный API для этого только с версии 1.8: get_field

Вот пример того, что вы можете сделать:

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 во всей кодовой базе, если переключитесь на пользовательскую модель пользователя.
  • get_field также имеет форму множественного числа (см. документы) для одновременного извлечения нескольких полей.
  • В общем, любые модификации форм во время выполнения (переопределение атрибутов полей и т. Д.) Происходят в методе __init__, поскольку именно здесь вы впервые получаете «настоящую» форму после того, как Django выполняет свою черную магию с метаклассами,см. переопределение атрибута required.
  • Если вы хотите переопределить переводимый текст, вам придется пройти через gettext и узнать об этом механизме, если вы хотите сделать это правильно.Конечно, вы можете просто жестко закодировать его по-французски.;)
  • Редактировать: Проверка формы происходит в методах форм validate и validate_{field}, инициируемых is_valid.Вам не нужно иметь эту логику внутри представления.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...