Custom Errors in Fields, on Django - python

I have a custom signup app from views:
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
userObj = form.cleaned_data
username = userObj['username']
email = userObj['email']
password1 = userObj['password1']
password2 = userObj['password2']
if password1 != password2:
return HttpResponse('password not match')
elif User.objects.filter(email=email).exists():
return HttpResponse('email must be unique')
elif User.objects.filter(username=username).exists():
return HttpResponse('username exists')
else:
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
mail_subject = 'Activation'
message = render_to_string('acc_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'token': account_activation_token.make_token(user),
})
to_email = form.cleaned_data.get('email')
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
return HttpResponse('Letter is sent')
else:
form = SignupForm()
return render(request, 'signup.html', {'form': form})
This is the only way I made test for unique email working (models didn't work, dont know why).
How can i make custom errors which i can put to my html using template tags {% if %}?
Thanks!

You have not tried using the Django message framework.
Look:
Adding a message
To add a message, call:
from django.contrib import messages
messages.add_message(request, messages.INFO, 'Hello world.')
Some shortcut methods provide a standard way to add messages with commonly used tags (which are usually represented as HTML classes for the message):
messages.debug(request, '%s SQL statements were executed.' % count)
messages.info(request, 'Three credits remain in your account.')
messages.success(request, 'Profile details updated.')
messages.warning(request, 'Your account expires in three days.')
messages.error(request, 'Document deleted.')
Displaying messages
get_messages(request)[source]
In your template, use something like:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
If you’re using the context processor, your template should be rendered with a RequestContext. Otherwise, ensure messages is available to the template context.
Even if you know there is only just one message, you should still iterate over the messages sequence, because otherwise the message storage will not be cleared for the next request.
The context processor also provides a DEFAULT_MESSAGE_LEVELS variable which is a mapping of the message level names to their numeric value:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %}
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
EDIT:
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
userObj = form.cleaned_data
username = userObj['username']
email = userObj['email']
password1 = userObj['password1']
password2 = userObj['password2']
if password1 != password2:
message = 'password not match'
elif User.objects.filter(email=email).exists():
message = 'email must be unique'
elif User.objects.filter(username=username).exists():
message = 'email must be unique'
messages.error(request, message)
else:
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
mail_subject = 'Activation'
message = render_to_string('acc_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'token': account_activation_token.make_token(user),
})
to_email = form.cleaned_data.get('email')
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
message = 'Letter was sent'
messages.success(request, message)
else:
form = SignupForm()
return render(request, 'signup.html', {'form': form})
Hope it Helps.

If we want to make a custom additional validation we can use messages.
First of all add in views:
from django.contrib import messages
Then we just add terms of sending message to our HTML, for example:
if User.objects.filter(email=email).exists():
messages.warning(request, 'email error.')
Now we can work with:
{% if messages %}
{% endif %}
In our HTML.
Also we can customise all our validations and ignore is_valid method.
Using:
from django.core import validators
we can use validate_email or validate_slug for fields we need.

Related

Django form does not work or CSRF_token aborted

Hello I am making Django App. I have a problem with my login form. Whenever I want to login,
form does not do anything or it throws csrf token error.
Views:
def loginView(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f"You successfully logged in {username}")
return redirect('home-page')
else:
form = AuthenticationForm()
return render(request, 'shop/login.html', {'form': form})
HTML TEMPLATE:
{% extends 'shop/base.html' %}
{% block content %}
<div class = "form-container">
<form class="form" method="POST">{% csrf_token %}
<label for="username">Email:</label>
{{form.username}}
<label for="password">Passoword:</label>
{{form.password}}
<button type="submit">Login</button>
</form>
</div>
{% endblock content %}
you have to check whether user existed or not in db if yes then login and redirect if not throw error or redirect on other page
def my_login(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
user = authenticate(username=username, password=password)
if user:
login(request, user)
return redirect('path')
else:
return redirect('path')
else:
return redirect('path')
else:
form = AuthenticationForm()
return render(request, "shop/login.html", {'form': form})
still get error add the complete traceback & i will also suggest you to read the full documentation of django https://docs.djangoproject.com/en/3.2/ref/contrib/auth/

if user.is_authenticated not getting logged in user django

Entirely new to python and django framework.
Trying to build a login/registration system.'
After registering, redirects to home but user is not authenticated (returns false always)
views.py
def register(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
fullname = form.cleaned_data.get('fullname')
password = form.cleaned_data.get('password1')
user = authenticate(username=username, fullname=fullname, password=password)
messages.success(request, f'Welcome to blaza {fullname}')
if user is not None:
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'accounts/signup.html', {'form': form})
home.html
{% extends 'base.html' %}
{% block title %} Home {% endblock %}
{% block content %}
{% if user.is_authenticated %}
Welcome, {{user.username}}!
Logout
{% else %}
<P>You are not logged in</P>
<p>Login here</p>
{% endif %}
{% endblock %}
It returns false always. "You are not logged".
I have tried {% if request.user.is_authenticated %} still not working.
‍‍i‍‍s‍_authenticated is a method not a property. I think you forgot the parenthesis.
Try this:
{% if request.user.is_authenticated() %}
Have you saved the user after signing up ?
myuser.save()
I have attached the code which worked for me.
def signup(request):
if request.method == 'POST':
username = request.POST['username']
name = request.POST['name']
email = request.POST['email']
pass1 = request.POST['pass1']
pass2 = request.POST['pass2']
myuser = User.objects.create_user(username, email)
myuser.set_password(pass1)
myuser.us_name = name
myuser.save()
messages.success(request, "Your account has been sucessfully created. ")
return redirect('signin')
return render(request, "authentication/signup.html")

Require Email When Creating an Account with Django

I've got a Django project, which requires users to be able create accounts to access content.
I'm using the UserCreationForm to do this.
In views.py I have
def register_user(request):
if request.method == "POST":
user_form = UserCreationForm(request.POST)
if user_form.is_valid():
new_user = user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data["password1"])
new_user.save()
template = "account/registration/registration_done.html"
context = {"new_user": new_user}
else:
# TODO: Handle exception
raise BaseException
elif request.method == "GET":
user_form = UserCreationForm()
template = "account/registration/register.html"
context = {"user_form": user_form}
else:
raise NotImplementedError
return render(request, template, context=context)
And then my template is:
{% extends "base.html" %}
{% block title %}Create an Account{% endblock %}
{% block content %}
<h1>Create an Account</h1>
<form action="." method="post">
{{ user_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Create my account"></p>
</form>
{% endblock %}
Which works okay. But when the create account form is displayed, it only has fields for the username, password, and password verification. There's no requirement that the user enter a valid email.
What I'd like to do is have a have the user be required to enter an email address, and then send them an email to ensure that the address is valid, and that they have access to is etc.
Surely this is a common enough pattern that there's already a way to implement is using Django's authentication? Or will I need to write all the forms and handling etc myself?
Override the Meta class of the UserCreationForm
In your forms.py
from django.contrib.auth.forms import UserCreationForm
class YourUserCreationForm(UserCreationForm)
class Meta:
fields = ("username", "email")
and use YourUserCreationForm instead

django user creation form with auth.user clean method

I have created a form to add users in my front-end but the form does not validate duplicated username.I am using auth.user model.
This is my code:
views.py
from django.contrib.auth.models import User, Group
#login_required(login_url='/login/')
#permission_required('auth.add_user',raise_exception=True)
def user_new(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(user.password)
user.save()
return redirect('userdetail', user.id)
else:
form = NewUserForm()
return render(request, 'ace/user_edit.html', {'form': form})
forms.py
class NewUserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username','first_name','last_name','password','email','is_active','is_staff','groups']
widgets = {
'username':TextInput(attrs={'class': u'form-control'}),
'first_name':TextInput(attrs={'class': u'form-control'}),
'last_name':TextInput(attrs={'class': u'form-control'}),
'password':PasswordInput(attrs={'class': u'form-control'}),
'email':EmailInput(attrs={'class': u'form-control'}),
'is_active':NullBooleanSelect(attrs={'class': u'form-control'}),
'is_staff':NullBooleanSelect(attrs={'class': u'form-control'}),
'groups':SelectMultiple(attrs={'class': u'form-control'}),
}
def clean_username(self):
username = self.cleaned_data['username']
user_exists = User.objects.get(username=username)
if user_exists:
raise ValidationError("User exists")
template
...
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<form method="POST" class="service-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-info">Salvar</button>
<a href="{% url 'userlist' %}">
<button class="btn btn-danger" type="button">Cancelar</button>
</a>
</form>
...
When I create a new user OK, but when a try create a user that same username of other I get a error:
The view ace.views.user_new didn't return an HttpResponse object. It
returned None instead.
If I add a print line "print form.errors" in view i get in console:
usernameUser
exists
Your view does not have an else statement for if, form is not valid it should render the template with form errors.
You need to change your view like this,
def user_new(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(user.password)
user.save()
return redirect('userdetail', user.id)
else:
return render(request, 'ace/user_edit.html', {'form': form})
else:
form = NewUserForm()
return render(request, 'ace/user_edit.html', {'form': form})
And also you need to add the tag {%for field in form%} {{field.error}}{%endfor%} along with the form fields and labels.
You need to make sure that your view returns a response for POST requests when the form is invalid. You can do this by moving the final return render() statement out of the else block.
def user_new(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
...
return redirect('userdetail', user.id)
else:
form = NewUserForm()
return render(request, 'ace/user_edit.html', {'form': form})
For registration django.contrib.auth User needs the username field to be unique. If you want to use other model field as unique (as unique registration field) and not the username, for example the email field, you can use this approach or use other registration bakends like django registration or django registration redux.
Instead of fixing the bug in your code I suggest to not invent the wheel and use excellent django-allauth package. It handles user login, logout, change password, registration and social sign in. I always start new projects from adding django-allauth - it handles all authentication problems with no effort.
You can use the saved time and effort to write actual application code instead of solving trivial user management details.
Also, the proper way to check for existence of the model instance is this:
user_exists = User.objects.filter(username=username).exists()
if user_exists:
raise ValidationError("User exists")

Django method to change User email not working

I am attempting to create a page where a user can see what their current email is and change it if they would like. I am just testing with a very simple form and a very simple HttpResponseRedirect if the form is not valid. However neither my email is changing for the user nor is my failure response if the form is not valid working. I am not sure what is causing this
forms.py:
class ChangeEmail(forms.Form):
email1 = forms.EmailField(label=u'Type new Email')
email2 = forms.EmailField(label=u'Type Email again')
views.py:
def change_email(request, username):
if request.method == 'POST':
user1 = User.objects.get(username=username)
form1 = ChangeEmail(request.POST)
if form1.is_valid():
user1.email = form.cleaned_data['email1']
form1.save()
return HttpResponseRedirect('/register/success')
else:
return HttpResponseRedirect('/stupid')
else:
user = User.objects.get(username=username)
email = user.email
form = ChangeEmail()
variables = RequestContext(request, {
'form': form,
'email': email
})
return render_to_response('registration/email.html', variables
Thanks for your help in advance.
EDIT:
The URL that I have mapped to render the form is /user/testuser/email. I am attempting to put in invalid input in to the fields to get an error message but when I push submit it redirects me back to /user/testuser page which displays info about the user. My change email template is below:
{% extends "base.html" %}
{% block title %}Change Email{% endblock %}
{% block head %}Change Email{% endblock %}
{% block content %}
<p> Current Email: {{ email }} </p>
<form method="post" action=".">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Change Email" />
</form>
{% endblock %}
ChangeEmail is a normal form. These don't have save methods - only ModelForms do. You're correctly setting the user email from the form's cleaned_data - but you should be saving the user1 object, not the form.
Also, it's best not to redirect away on validation failure. Leave out that first else clause, and move the variables/render_to_response lines back one indentation level, and the form will be redisplayed with any errors.
views.py:
def change_email(request, username):
# a common django idiom for forms
form1 = ChangeEmail(request.POST or None)
user1 = User.objects.get(username=username)
if form1.is_valid():
#check that emails are the same
if form.cleaned_data['email1'] == form.cleaned_data['email2']:
user1.email = form.cleaned_data['email1']
#Save the user object here, since we're not dealing with a ModelForm
user1.save()
return HttpResponseRedirect('/register/success')
# We're presenting them with the empty form if something went wrong
# and redisplaying. The form's field errors should be printed out in
# the template
else:
user = User.objects.get(username=username)
email = user.email
variables = RequestContext(request, {
'form': form,
'email': email
})
return render_to_response('registration/email.html', variables)

Categories