问题
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.
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.
回答1:
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
来源:https://stackoverflow.com/questions/41088567/django-registration-overriding-the-default-fields