realnot
realnot

Reputation: 753

Django-Registration: Overriding the default fields

Yesterday I faced a problem trying to override the RegistrationForm of Django-Registration app. The class RegistrationForm inherit from UserCreationForm of Django, which is based on ModelForm, so I created my custom class inheriting from RegistrationForm in this way:

from django import forms
from django.contrib.auth.models import User

class MyRegistrationForm(RegistrationForm):
    class Meta:
        model = User
        fields = ('username', 'email', 'password1', 'password2')
        widgets = {
            'username': forms.TextInput(
                attrs={'placeholder': 'hasdsa', 'class': 'form-control'}),
            'email': forms.EmailInput(
                attrs={'placeholder': 'hasdsa', 'class': 'form-control'}),
            'password1': forms.PasswordInput(
                attrs={'placeholder': 'hasdsa', 'class': 'form-control'}),
            'password2': forms.PasswordInput(
                attrs={'placeholder': 'hasdsa', 'class': 'form-control'}),
        }

I set the Meta class in this way because the model User and the fields username, email, password1, password2 are the same attribute of UserCreationForm. This code live in a module named accounts / forms.py and is called directly from accounts / urls.py in this way:

from django.conf.urls import include, url

from registration.backends.hmac import views

from accounts.forms import MyRegistrationForm

urlpatterns = [
    url(r'^register/$', views.RegistrationView.as_view(form_class=MyRegistrationForm), name='registration_register'),
    url(r'', include('registration.backends.hmac.urls')),
]

The goal here is overriding the attributes of an input field of a form with widgets adding attributes like class or placeholder or change the labels of the form or adding error_messages and so on.

As explained in Django-Registration docs to achieve this you just need to pass your custom form to form_class parameter of the RegistrationView. Done. It doesn't works and I don't know why.

registration_form.html - context analysis

As you see in the screenshot, DDT (Django Debug Toolbar) reports the fields of the form and all data available from there. The output of {{ form.as_p }} tag return this result:

<form method="post" action=".">
    <input type='hidden' name='csrfmiddlewaretoken' value='dNeT0R1JPIBtsrGCbcyPQjPLDAW7P7qb' />
    <p><label for="id_username">Username:</label> <input class="form-control" id="id_username" maxlength="30" name="username" placeholder="hasdsa" type="text" /> <span class="helptext">Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.</span></p>
    <p><label for="id_email">Email:</label> <input id="id_email" name="email" type="email" /> <span class="helptext">email address</span></p>
    <p><label for="id_password1">Password:</label> <input id="id_password1" name="password1" type="password" /></p>
    <p><label for="id_password2">Password confirmation:</label> <input id="id_password2" name="password2" type="password" /> <span class="helptext">Enter the same password as before, for verification.</span></p>
    <input type="submit" value="Submit" />
</form>

And the bug come from there. As you can see, only the username field is changed. You can see the attribute class and placeholder overrided in the widget. But all other fields are still the same. Just a question: Why?

Instead to set the model and fields attributes of the meta class in the way reported above, I tried with:

class MyRegistrationForm(RegistrationForm):
    class Meta(RegistrationForm.Meta):
        widgets = { ... }

We don't need to change those attributes, we are only interested on widgets, but the result is the same, it doesn't works.

I'd also like to know what is the best way to change the widgets of all forms in a project. Overriding each form in this way? Using a template tag and filter each form field? Using a middleware? If you use a framework like bootstrap, probably you want to have the attribute class="form-control" for each input field. What is the best way to achieve this?

Thanks for your time and support.

Upvotes: 1

Views: 1936

Answers (2)

Mustaq Mohammad
Mustaq Mohammad

Reputation: 1

Try this

class CreateUserForm(UserCreationForm): 
    password1 = forms.CharField(widget=forms.PasswordInput(attrs={ 'class': 'form-control form-control-user', 'placeholder': 'Password'}))
    password2 = forms.CharField(widget=forms.PasswordInput(attrs={ 'class': 'form-control form-control-user', 'placeholder': 'Repeat Password'}))

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email', 'password1', 'password2']
        widgets = {
            'first_name': forms.TextInput(attrs={'class': 'form-control form- 
                                                       control-user',
                                             "placeholder": "First Name"}),
            'last_name': forms.TextInput(attrs={'class': 'form-control form- 
                                 control-user', "placeholder": "Last Name"}),
            'email': forms.TextInput(attrs={'class': 'form-control form-control-user', "placeholder": "Email"}),

        }

Upvotes: 0

Nico JL
Nico JL

Reputation: 429

Try like this:

class SignUpForm(UserCreationForm):
    username = forms.Field(widget=forms.TextInput(attrs={'class':'form-control'}))
    email = forms.Field(widget=forms.EmailInput(attrs={'class':'form-control'}))
    password1 = forms.Field(widget=forms.PasswordInput(attrs={'class':'form-control'}))
    password2 = forms.Field(widget=forms.PasswordInput(attrs={'class':'form-control'}))

class Meta:
    model = User    
    fields = ('username','email','password1',)  

Works for me

Upvotes: 0

Related Questions