Переопределение виджета вида на основе класса Django

Скажем, у меня есть базовая форма CreateView, например, чтобы позволить новым пользователям регистрироваться на сайте:

from django.contrib.auth import get_user_model
from django.http import HttpResponse
from django.views.generic import CreateView

User = get_user_model()


class Signup(CreateView):

    model = User
    fields = ['first_name', 'last_name', 'email', 'password']

Я просто попробовал это и обнаружил, что поле пароля отображается в виде обычного текста; как бы я стал переопределять представление, чтобы вместо этого использовать forms.PasswordInput()? (Я понимаю, что проще всего просто определить форму вручную, но мне просто интересно, как вы это сделаете.)

Ответ 1

Вы можете переопределить get_form() и изменить форму для изменения виджета в поле пароля:

from django import forms

class Signup(CreateView):
    model = User
    fields = ['first_name', 'last_name', 'email', 'password']

    def get_form(self, form_class):
        form = super(Signup, self).get_form(form_class)
        form.fields['password'].widget = forms.PasswordInput()
        return form

Но еще лучший способ - просто создать собственный класс формы. В пользовательском классе просто установите widgets в класс Meta. Вот так:

from django import forms

class SignupForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email', 'password']
        widgets = {
            'password': forms.PasswordInput()
        }

class Signup(CreateView):
    form_class = SignupForm
    model = User

Обычно вы также добавляете собственный класс формы в файл forms.py.

Ответ 2

Не уверен, что это повлияло на более ранние версии Django, но в более поздних версиях get_form() должен иметь значение по умолчанию form_class=None при переопределении этого метода.

Обновленный пример (Python 3, Django 2.2) будет выглядеть так:

from django import forms

class Signup(CreateView):
    model = User
    fields = ['first_name', 'last_name', 'email', 'password']

    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        form.fields['password'].widget = forms.PasswordInput()
        return form

https://docs.djangoproject.com/en/2.2/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin