24👍
You’re showing the form with {{ form }}
on the template. That itself should show all the validation errors by default, but in your case, you’re redirecting to some other page if the form is invalid. So you can never show the errors unless you pass the errors with the GET parameters. You could change your view to this to get the errors on the signup page itself –
def register_user(request):
args = {}
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('../../membership/register_success')
else:
form = RegistrationForm()
args['form'] = form
return render(request,'registration/registration_form.html', args)
How this works is, if the request method is POST, the form gets initiated with the POST data, then it’s validated with the is_valid()
call, so the form object now has the validation error messages if it’s invalid. If it’s valid, it’s saved and redirected. If not valid, it comes to the args['form'] = form
part where the form object with the error messages is set to the context and then passed to render.
If the request method is not POST, then a form object with no data is instantiated and passed to render()
.
Now your template should show all the error messages just below each field if there is any error.
15👍
forms.py
from django import forms
class RegistForm(forms.Form):
name = forms.CharField(required=True)
email = forms.EmailField(required=True)
password = forms.CharField(required=True)
views.py
from django.shortcuts import render
from django.views.generic import TemplateView
import forms
class Register(TemplateView):
def get(self, request):
return render(request, 'register.html', {})
def post(self, request):
form = forms.RegistForm(request.POST)
if form.is_valid():
print(1)
else:
print(form.errors)
content = {'form':form};
return render(request, 'register.html', content)
register.html
<form action="{% url 'register' %}" method="post">
{% csrf_token %}
<fieldset>
<label for="name">Name:</label>
<input type="text" id="name" name="name" value="">
{{ form.errors.name }}
<label for="mail">Email:</label>
<input type="text" id="mail" name="email">
{{ form.errors.email }}
<label for="password">Password:</label>
<input type="password" id="password" name="password">
{{ form.errors.password }}
</fieldset>
<button type="submit">Sign Up</button>
<p class="message">Already registered? <a href="{% url 'login' %}">Login</a></p>
</form>
** Feel free to copy code and enjoy! **
- [Django]-How to implement followers/following in Django
- [Django]-Adding to the "constructor" of a django model
- [Django]-Unable to get results from Google text to speech api while streaming audio from web
5👍
Why not just do something like this:
...
if User.objects.filter(email=email):
raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
return email
...
If the user already registered, have it raise a validation error. If you don’t want it to do this, you can do something like:
...
email_exists = User.objects.filter(email=email):
if email_exists and email_exists.username != username:
raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
return email
...
To display the form errors, you use form.is_valid()
to make sure that it passes validation. Django says the following for custom validations:
Note that any errors raised by your Form.clean() override will not be associated with any field in particular. They go into a special “field” (called __all__), which you can access via the non_field_errors() method if you need to. If you want to attach errors to a specific field in the form, you need to call add_error().
Then in your template you can use something like {{ form.non_field_errors }}
, etc.
See this section in the Django docs, under Using a form in a view
and Customizing the form template
:
https://docs.djangoproject.com/en/dev/topics/forms/
- [Django]-Django & Redis: How do I properly use connection pooling?
- [Django]-Django Manager Chaining
- [Django]-Django Server Error: port is already in use
0👍
Class based views are easier.
from django.views import generic
from .forms import RegistrationForm
class RegistrationView(generic.CreateView):
template_class = 'registration/registration_form.html'
form_class = RegistrationForm
success_url = '/success/url'
def form_valid(self, form):
# add a log after save or whatever
super(RegistrationView, self).form_valid(self, form)
The clean methods are automatic with forms and messages render as such,
class based views make life a lot easier and your code DRYer.
- [Django]-Is there a built-in login template in Django?
- [Django]-Django REST Framework: 'BasePermissionMetaclass' object is not iterable
- [Django]-How to stream an HttpResponse with Django
0👍
Have resolved this error by the following:
from django.core.exceptions import ValidationError
try:
except ValidationError as e:
- [Django]-Easy-to-use django captcha or registration app with captcha?
- [Django]-Django: using ModelForm to edit existing database entry
- [Django]-How to manage local vs production settings in Django?