Django puts my password in browser url field - python

I have the following view class:
class LoginView(View):
form_class = LoginForm
template_name = 'workoutcal/login.html'
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(email = email, password = password)
if user is not None:
if user.is_active:
login(request, user)
return calendar(request)
else:
return render(request, self.template_name, {'form':form})
else:
form['custom_error_message'] = 'Invalid user'
return render(request, self.template_name, {'form':form})
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form':form})
And this template:
login.html
{% extends "workout/base.html" %}
{% block logoutwidget %}{% endblock %}
{% block content %}
<form action="/workoutcal/login/">
{% include "workoutcal/form_disp_errors.html" %}
<input type="submit" value="Log in">
</form>
{% endblock %}
form_disp_errors.html
{% csrf_token %}
{{ form.custom_error_message }}
{{ form.non_field_errors }}
{% for field in form.visible_fields %}
<div class="row">
<div class="col-xs-2">
{{ field.label_tag }}
</div>
<div class="col-xs-2">
{{ field }}
</div>
<div class="col-xs-3">
{{ field.errors }}
</div>
</div>
{% endfor %}
When I go to workoutcal/login, type in an incorrect username and password (user doesn't exist), the page goes to workoutcal/login again, but with this url:
http://localhost:8000/workoutcal/login/?csrfmiddlewaretoken=ZywQUh7gnNfaHi8FcA3be4ynLB7SpGgwdJ0UxGzUuRYp0G0Y9LQ9e24Jx8Q1OD3Y&email=myemail%40hotmail.com&password=MYPASSWORD
As you can see in the end of the link, the password is displayed. This is obviously not good. However, I can't understand why it happens. Any ideas?

You have to use HTTP method POST, for that you must set attribute method="post" to your form tag. Like that:
<form method="post" action="/workoutcal/login/" >
With method POST request will send query string (key/value pairs) in HTTP message body instead of URL.
Note: consider using PUT/PATCH to update objects and DELETE to remove for RESTful APIs (by default Django will use method POST for all these cases).

Related

why my user can't be authenticated after register,but can after login

I started an app named 'blogs' as a programming book required,when I finished the 'register' function which can register a user and login with it.I found that the user can be added to database normally,but it can't be authenticated.but when I used the username login normally,it can work!I checked my codes for many times,but I can't find the fault.Please give me some help,thank you very much!
Here are my codes:
users:views.py:
def register(request):
if request.method != 'POST':
form = UserCreationForm()
else:
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
authenticated_user = authenticate(username=new_user.username, password=request.POST['password1'])
login(request,authenticated_user)
return HttpResponseRedirect(reverse('blogs:index'))
context = {'form':form}
return render(request,'users/register.html',context)
users:register.html:
{% extends "blogs/base.html" %}
{% block content %}
<form method="post" action="{% url 'users:register' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">register</button>
<input type="hidden" name="next" value="{% url 'blogs:index' %}" />
</form>
{% endblock content %}
blogs:base.html:
Welcome to blog -
{% if user.is_authenticated %}
hello,{{ user.username }} -
logout
{% else %}
register -
login
{% endif %}
{% block content %}{% endblock content %}
Where do you get 'password1' from? Probably you have it in your login.html and confuse. Change that line with authenticated_user = authenticate(username=new_user.username, password=new_user.password) . Hope it will help.

Django - Form not displaying in HTML when receiving an error

In my Django project, I display a form when a user sends a GET request.
Here's the code for this:
form = SignUpForm()
if request.method == 'POST':
....
else:
return render(request, 'users/signup.html', {'form': form})
HTML FOR THIS:
<form method="POST" class="signupform">
{% csrf_token %}
{% for field in form %}
<div class="fields">{{ field }}</div>
{{ field.errors }}
<br>
{% endfor %}
<input class="submitButton" type="submit" value="Sign Up">
</form>
If the user sends a post request, I set form = SignUpForm(request.POST) and check if a user with the same username as someone else exists. When this happens, I want to render the whole page again, including the form fields, with an error message displayed.
Here's my current code for this:
try:
user = User.objects.get(username=form.cleaned_data['username'])
return render(request, 'users/signup.html', {'error': 'Username field has already been taken', 'form':form})
except User.DoesNotExist:
...
HTML:
{% if error %}
<form method="POST" class="signupform">
{% csrf_token %}
{% for field in form %}
<div class="fields">{{ field }}</div>
{{ field.errors }}
<br>
{% endfor %}
<input class="submitButton" type="submit" value="Sign Up">
</form>
{{ error }}
{% endif %}
However when this error occurs, The error message does show but none of the form fields are displayed on the screen. They disappear. Does anybody know the issue? Thank you.
Updated code:
context = []
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
if not form.cleaned_data['password'] == form.cleaned_data['confirmPassword']:
context["error"] = 'Username field has already been taken'
else:
raise Http404
else:
form = SignUpForm()
context['form'] = form
return render(request, 'users/signup.html', context)
View.py:
context = {}
if request.method == 'POST':
form = SignUpForm(request.POST)
try:
user = User.objects.get(username=form.cleaned_data['username'])
messages.error(request, 'Username field has already been taken')
return redirect('users/signup.html')
except User.DoesNotExist:
...
else:
form = SignUpForm()
context['form'] = form
return render(request, 'users/signup.html', context)
template:
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}

Delete button in a template is inactive

enter code hereI have a group_edit.html which permit to update info of a group and delete it.
Upade(save) works great but button for delete is doing nothing.
Thanks for help:
My group_edit.html:
{% block page %}
<form method="POST">
{% csrf_token %}
<div class="col-lg-4 col-md-4 col-sm-4 content">
{% bootstrap_form form %}
<button type="submit" class="btn btn-pink pull-right">Save</button>
<button type="reset" class="btn btn-warning pull-left">Delete</button>
</div>
Back to list
</form>
{% endblock %}
My confirm_delete.html template:
{% block title %}Delete{% endblock %}
{% block heading %}<h3 class="page-header-center">Object Delete</h3> {% endblock %}
{% block page %}
<form method="post">{% csrf_token %}
<p>Are you sure you want to delete "{{ obj }}"?</p>
<input type="submit" value="Confirm" class="btn btn-warning">
Cancel
</form>
{% endblock %}
my views.py:
def group_edit(request, group_id):
form = GroupForm(instance=Group.objects.get(group_id=group_id))
if request.method == "POST":
form = GroupForm(request.POST, instance=Group.objects.get(group_id=group_id))
if form.is_valid():
form.save()
messages.success(request, 'Group saved') # message for inform user of success - See messages in html file
return redirect(group_list)
return render(request, 'imports/group_edit.html', {
"group_id": group_id,
"form": form,
})
def confirm_delete(request, group_id):
obj = GroupForm(instance=Group.objects.get(group_id=group_id))
if request.method == "POST":
obj.delete()
messages.success(request, 'Deleted') # message for inform user of success - See messages in html file
return render(request, 'imports/group_list.html')
context = {
"obj": obj
}
return render(request, "imports/confirm_delete.html", context)
and my urls.py:
path('group_edit/<int:group_id>/', views.group_edit, name='group-edit'),
path('confirm_delete/<int:group_id>/', views.confirm_delete, name='confirm-delete'),
In your link, the span of <a> is empty. So instead of
Delete
it should be:
Delete
Probably it is better to specify the {% url ... %} parameters with named parameters:
Delete

Python Django How to save choice using model class "CHOICE"?

In my models.py, I have class with LEVEL_CHOICES and Level.
First I builded my project with a textfield Level and it worked. Then I decided to change my Level in order to give users only certain choices. Therefore I edited my models.py and I have now:
class Eleve(models.Model):
FIRST = 'FIRST'
SECOND = 'SECOND'
THIRD = 'THIRD'
LEVEL_CHOICES = (
('FIRST', 'School'),
('SECOND', 'HighSchool'),
('THIRD', 'University'),
)
Level = models.CharField(max_length=3, choices=LEVEL_CHOICES, default='FIRST')
I think that there is a problem in my views.py because I'am able to save class Eleve through Admin app. I'm also using a decorator in order to have REcaptchaV2.
def Form(request):
form = ResgisterStud(request.POST)
if request.recaptcha_is_valid and form.is_valid():
form.save(commit=False)
form.save()
return render(request, 'form.html', {'form': form})
else:
return render(request, 'form.html', {'form': form})
my forms.py
class ResgisterStud(forms.ModelForm):
class Meta:
model = Eleve
My Form.html
<form action="{% url "form" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-md-6 form-group">
{{ form.Level|add_class:"form-control" }}
</div>
<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="form-group g-recaptcha" data-sitekey="***"></div>
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endfor %}
{% endif %}
</form>

Python/Django: How to display error messages on invalid login?

I'm trying to do the Login for my Django (2.0) website, so far I've got the login working for existing accounts. I'm using the built-in login function.
Now I want to display an error message when you enter an invalid account, for example "Invalid username or password!". But I have no idea how to go about this.
Right now it just refreshes the login page when your enter an invalid account. Any help is appreciated!
Login.html
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}
Login view
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
auth_login(request, user)
return redirect('index')
else:
form = AuthenticationForm()
return render(request, 'todo/login.html', {'form': form})
in your template
{% for message in messages %}
<div class="alert alert-success">
<a class="close" href="#" data-dismiss="alert">×</a>
{{ message }}
</div>
{% endfor %}
in view
from django.contrib import messages
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
auth_login(request, user)
return redirect('index')
else:
messages.error(request,'username or password not correct')
return redirect('login')
else:
form = AuthenticationForm()
return render(request, 'todo/login.html', {'form': form})
You should just add inside your template:
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
{% if form.errors %}
<p>username or password not correct</p>
{% endif %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}
Updating for Django 2.0:
For individual field errors (e.g) :
<input type="text" class="form-control my-4" id="id_username" placeholder="Username" name="username">
{% for error in form.username.errors %}
<p class="text-danger">{{ error }}</p>
{% endfor %}
For non field errors (e.g if password is incorrect):
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p class="text-danger">{{ error }}</p>
{% endfor %}
{% endif %}
You should place the above at the end of all fields.
You already have {{ form.as_p }} in your template, so Django will show any form errors.
The problem is that the AuthenticationForm takes request as its first argument. You can then use form.is_valid() to check whether the username and password are valid and that the user is active, instead of fetching the data from request.POST manually.
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request, request.POST)
if form.is_valid():
auth_login(self.request, form.get_user())
return redirect('index')
else:
form = AuthenticationForm(request)
return render(request, 'todo/login.html', {'form': form})
Another option would be to use the built-in LoginView instead of writing your own:
from django.contrib.auth import views as auth_views
urlpatterns = [
...
path('accounts/login/', auth_views.LoginView.as_view(template_name='todo/login.html')),
...
]
Then set LOGIN_REDIRECT_URL in your settings.
LOGIN_REDIRECT_URL = 'index'

Categories