Django request.POST.get() returns None - python

I face a problem and I can't find a solution.
I'm trying to redirect to the previous page after login. Somehow the ?next=request.path returns none when trying to request.POST.get() after submission.
This is my Html code that directs the user to the login page, taking the request.path as "next page after login" value.
{% if user.is_authenticated %}
<button class="btn" data-toggle="modal" data-target="#inquiryModal">
<a class="btn btn-primary border rounded-0"
role="button" href="#">Make an Inquiry</a>
</button>
{% else %}
<a class="btn btn-primary border rounded-0" role="button"
href="{% url 'login' %}?next={{ request.path|urlencode }}"
>Make An Inquiry</a>
{% endif %}
This is the login page html code.
<div class="login-clean" style="background-color: #fff;">
<form action="{% url 'login' %}" method="POST">
{% csrf_token %}
<!--- ALERTS -->
{% include 'partials/_alerts.html' %}
<div class="form-group">
<input class="form-control" type="email" name="email" placeholder="Email"></div>
<div class="form-group">
<input class="form-control" type="password" name="password" placeholder="Password">
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" type="submit">Log In</button>
</div>
</form>
</div>
Views.py file
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
valuenext = request.POST.get('next')
print(valuenext)
user = auth.authenticate(username=email, password=password)
# if user is found and not from listing page login and redirect to dashboard
if user is not None and valuenext == "":
auth.login(request, user)
messages.success(request, 'You are now succesfully logged in')
return redirect('dash_inquiries')
# if user is found and from specific listing page login and redirect to the listing
elif user is not None and valuenext != "":
auth.login(request, user)
print("success")
messages.success(request, 'You are now logged in')
return redirect(valuenext)
else:
messages.error(request, 'Invalid credentials')
return redirect('login')
else:
return render(request, 'accounts/login.html')
What am I doing wrong here? The next value is passed in the url when directing to the login page, but I don't seem to correctly get() the next value in my backend as it keeps returning None.
Thanks in advance.

Clicking on following button will send a GET request.
<a class="btn btn-primary border rounded-0" role="button"
href="{% url 'login' %}?next={{ request.path|urlencode }}">Make An Inquiry</a>
This get request will render accounts/login.html template.
You're parsing request.POST.get('next') for POST requests only. But there is no next in
<form action="{% url 'login' %}" method="POST">
You need your form tag to look like
<form action="{% url 'login' %}next={{ next }}" method="POST">
To solve above issue, you need to parse 'next' for request.GET, and add it to context for response.
if request.method == 'POST':
# handle POST
else:
next = request.GET.get('next', '')
context = {'next': next}
return render(request, 'accounts/login.html', context=context)
And then, add this next into form.action.
<form action="{% url 'login' %}next={{ next }}" method="POST">

Okay, so I didn't make sure I passed the next value into the login form, therefore the solution was to add a hidden input to get the next value in the request:
<input type="hidden" name="next" value="{{ request.GET.next }}" />

Related

How to implement Like Dislike button for anonymous user in Django?

How can I implement like and dislike button functionality for anonymous users in my django website?
I am recently developing django website,and decided not to use User Login & Logout for the purpose of more visiting users.
The problem is how to do implement IP Address instead of "request.user".
Anyone knows how to set IP address as if like a user for "like and dislike button"???
Below is my code so far (set request.user for like dislike function):
#views.py Dislike is the same code.
#login_required(login_url="login")
def Like(request, slug):
add = Add.objects.get(slug=slug)
# remove dislike when user hit like.
is_dislike = False
for dislike in add.dislikes.all():
if dislike == request.user:
is_dislike = True
break
if is_dislike:
add.dislikes.remove(request.user)
# add like
is_like = False
for like in add.likes.all():
if like == request.user:
is_like = True
break
if not is_like:
add.likes.add(request.user)
if is_like:
add.likes.remove(request.user)
next = request.POST.get("next", "/")
return HttpResponseRedirect(next)
#review.html inside templates
<div class="rate-added-rule">
<form action="{% url 'like' added_data.slug %}" method="POST">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<button type="submit" class="like-button">
<i class="far fa-thumbs-up">LIKE<span>VOTES: {{ added_data.likes.all.count }}</span></i>
</button>
</form>
<form action="{% url 'dislike' added_data.slug %}" method="POST">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<button type="submit" class="dislike-button">
<i class="far fa-thumbs-down">DISLIKE<span>VOTES: {{ added_data.dislikes.all.count }}</span></i>
</button>
</form>
</div>

Get Google Bar link to change after pressing button bootstrap python

I'm making a web page with python. My login render function looks something like this:
#app.route('/Login', methods = ['GET', 'POST'])
def Login():
if request.method == 'POST':
username = request.form.get('loginUsername')
password = request.form.get('loginPassword')
if //username password doesn't exist:
flash('No such username and password', category='error')
else: //username password does exist:
flash('Successful Login!', category = 'success')
return render_template('home.html')
else:
return render_template('Login.html')
My current google link would be something like:
If I sign in, I want my link to change to:
But it stays at /Login. How do I get the link to change? This is causing me a lot of trouble.
This is my Login.html
{% extends "layout.html" %}
{% block content %}
<div class="jumbotron">
<h1>Login</h1>
</div>
<div class="container">
<form method="POST">
<!-- Username input -->
<div class="form-outline mb-4">
<p>Username: </p><input type="text" id="loginUsername" class="form-control" name="loginUsername" placeholder="Username" />
<label class="form-label" for="floatingInput"></label>
</div>
<!-- Password input -->
<div class="form-outline mb-4">
<p>Password: </p><input type="password" id="loginPassword" class="form-control" name="loginPassword" placeholder="Password" />
<label class="form-label" for="floatingInput"></label>
</div>
<br />
<!-- Submit button -->
<button type="submit" class="btn btn-primary mb-4">Sign in</button>
</form>
</div>
{% endblock %}

Trouble linking HTML login code with apps.py Python code with Flask

I have this code which runs in the navbar, it's meant to implement a login/registration form but without leaving the home page, its a toggler with a data-target="#login-form":
<i class="icon-user"></i> Sign In
How do I change the #app.route so that it targets the login-form that's implemented within the home page? Python code used:
#app.route('/')
def home():
# Check if user is loggedin
if 'loggedin' in session:
# User is loggedin show them the home page
return render_template('home.html', username=session['username'])
# User is not loggedin redirect to login page
return redirect(url_for('home'))
#app.route('/login/', methods=['GET', 'POST'])
def login():
cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
# Check if "username" and "password" POST requests exist (user submitted form)
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
print(password)
# Check if account exists using MySQL
cursor.execute('SELECT * FROM users WHERE username = %s', (username,))
# Fetch one record and return result
account = cursor.fetchone()
if account:
password_rs = account['password']
print(password_rs)
# If account exists in users table in out database
if check_password_hash(password_rs, password):
# Create session data, we can access this data in other routes
session['loggedin'] = True
session['id'] = account['id']
session['username'] = account['username']
# Redirect to home page
return redirect(url_for('home'))
else:
# Account doesnt exist or username/password incorrect
flash('Incorrect username/password')
else:
# Account doesnt exist or username/password incorrect
flash('Incorrect username/password')
return render_template('home.html')
<div class="modal fade c-content-login-form" id="login-form" role="dialog">
<div class="modal-dialog">
<div class="modal-content c-square">
<div class="modal-header c-no-border">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<h3 class="c-font-24 c-font-sbold">Good Afternoon!</h3>
<p>Let's make today a great day!</p>
<form>
<div class="form-group" method="post">
<label for="username" class="hide">Username</label>
<input type="username" class="form-control input-lg c-square" name="username" id="username" placeholder="Username">
</div>
<div class="form-group">
<label for="password" class="hide">Password</label>
<input type="password" class="form-control input-lg c-square" name="password" id="password" placeholder="Password">
</div>
<div class="form-group">
<div class="c-checkbox">
<input type="checkbox" id="login-rememberme" class="c-check">
<label for="login-rememberme" class="c-font-thin c-font-17">
<span></span>
<span class="check"></span>
<span class="box"></span>
Remember Me
</label>
</div>
</div>
<div class="form-group">
<input type="submit" value="Login" class="form-control btn btn-success btn c-theme-btn btn-md c-btn-uppercase c-btn-bold c-btn-square c-btn-login" name="">Login</input>
Forgot Your Password ?
</div>
<div class="clearfix">
<div class="c-content-divider c-divider-sm c-icon-bg c-bg-grey c-margin-b-20">
<span>or signup with</span>
</div>
<ul class="c-content-list-adjusted">
<li>
<a class="btn btn-block c-btn-square btn-social btn-twitter">
<i class="fa fa-twitter"></i>
Twitter
</a>
</li>
<li>
<a class="btn btn-block c-btn-square btn-social btn-facebook">
<i class="fa fa-facebook"></i>
Facebook
</a>
</li>
<li>
<a class="btn btn-block c-btn-square btn-social btn-google">
<i class="fa fa-google"></i>
Google
</a>
</li>
</ul>
</div>
</form>
I understand linking specific pages but what if it isn't exactly a page you want to link
You already have the navbar and the modal form there. Now you need some javascript that makes the link toggle the modal box visibility.
And also some javascript that intercepts the form submission, prevents it from loading another page, grabs the form data, and posts it to the flask endpoint. Please lookup javascript fetch() post data.
Edit: please check Matiiss comment below. It seems Bootstrap already provides the js code you need.
This is my approach to have a login forma and home page on the same route (could probably use two templates but this works too):
The main file:
from flask import Flask, redirect, url_for, request, render_template
from wtforms import StringField, SubmitField
from wtforms.validators import InputRequired
from flask_wtf import FlaskForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_key_'
user_logged_in = False
class LoginForm(FlaskForm):
username = StringField('Username', validators=[InputRequired()])
password = StringField('Password', validators=[InputRequired()])
submit = SubmitField('Login')
#app.route('/', methods=['GET', 'POST'])
def home():
global user_logged_in
if user_logged_in:
return render_template('home.html', logged_in=user_logged_in)
else:
form = LoginForm()
if form.validate_on_submit():
user_logged_in = True
return redirect(url_for('home'))
return render_template('home.html', logged_in=user_logged_in, form=form)
if __name__ == '__main__':
app.run(debug=True)
Obviously you need to use your user login validation, this is just to for testing (logged_in variable)
(Also I spent like 20 min trying to figure out why I couldn't submit form and it was because I didn't include {{ form.hidden_tag() }} in my form)
The template (super simple):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
{% if logged_in %}
<h1>You are logged in</h1>
<p>{{ logged_in }}</p>
{% else %}
<form action="{{ url_for('home') }}" method="POST">
{{ form.hidden_tag() }}
<div>
{{ form.username.label }}
{{ form.username }}
</div>
<div>
{{ form.password.label }}
{{ form.password }}
</div>
{{ form.submit }}
</form>
<p>{{ logged_in }}</p>
{% endif %}
</body>
</html>
Basically You check if user is logged in and then just simply pass that variable to the template and there is a huge if statement, I should tho point out that using a modal in this case is not the best idea, you have to just show completely only the login part otherwise someone may open DevTools and just delete that modal and gain accesss to the home page
If You have any questions, ask

django form not posting, but other form on page does?

I have two forms on a page. The first form properly sends a POST request to my view but the second form sends a GET (I need it to also send a POST). I've made this mistake before and this time I made sure that the button is set to "submit", but for some reason it still sends a GET.
form 1 (working as intended):
<form method="POST">
{% csrf_token %}
<div class="row form-row">
<div class="col-sm-6">
<div class="form-group">
<label for="start_date">Start</label>
<input class="form-control" type="text" data-flatpickr data-alt-input="true" data-date-format="Y-m-d" name="start_date" data-enable-time="true">
</div>
<div class="form-group">
<label for="end_date">End</label>
<input class="form-control" type="text" data-flatpickr data-alt-input="true" data-date-format="Y-m-d" name="end_date" data-enable-time="true">
</div>
</div>
</div>
<input type="hidden" name="eventtype" value="availability">
<button class="btn btn-primary" type="submit">Save changes</button>
</form>
form 2 (sends a GET but I want this to POST):
<form method="POST">
{% csrf_token %}
{% if form.errors %}{{form.errors}}{% endif %}
<input type="hidden" name="pk" value="{{ i.id }}">
<input type="hidden" name="eventtype" value="invite">
<button class="btn btn-primary" type="submit">Confirm</button>
</form>
views.py
def createevent(request):
if request.method == 'GET':
<<code>>
else:
try:
eventtype = request.POST.get('eventtype', None)
print(eventtype)
if eventtype == "availability":
form = EventForm(request.POST)
newEvent = form.save(commit=False)
newEvent.mentor_user = request.user
newEvent.requester_user = None
newEvent.notes = None
newEvent.save()
elif eventtype == "invite":
form = EventForm(request.POST)
updatedEvent = form.save(commit=False)
updatedEvent.isConfirmed = True
updatedEvent.save()
return redirect('createevent')
except ValueError:
print(form.errors)
return render(request, 'events/createevent.html', {'form':EventForm(), 'error':'There was an error. Please make sure you entered everything correctly!'})
urls.py
# Events
path('events/create', views.createevent, name='createevent'),
# path('calendar/<slug:slug>', views.viewevent, name='viewevent'),
path('events/<int:pk>/edit', views.updateevent, name='updateevent'),
console output for form 1 and form 2:
"GET /events/create?csrfmiddlewaretoken=<<redacted>>&pk=2&eventtype=invite HTTP/1.1" 200 25560
"POST /events/create?csrfmiddlewaretoken=<<redacted>>&pk=2&eventtype=invite HTTP/1.1" 302 0
Set the action of form to your url path.
Look at this:
<form name="form" method="POST" action="{% url 'your_url_name' %}">
The issue ended up being the form was wrapped in another form tag further up in the template code. When I clicked the Submit button, the Submit button was firing on the first form and not the second. Just a bad copy/paste.

Django login gives http 500 error

So I'm making a login system for my Django application. It works on my dev side absolutely fine, but in prod it doesn't work if I submit the correct username and password (It gives a 500 error). I'm not sure which of the two lines I've pointed out in views.py is the issue, but I figure it must be one of those two since if I do enter an incorrect user then I get redirected fine, even in prod.
The code on my dev and prod side are EXACTLY the same - the only difference is in the settings
DEBUG = True
ALLOWED_HOSTS = []
^ The above is my dev settings, but in prod DEBUG is False and ALLOWED_HOSTS has been filled out with the appropriate names.
In views.py:
def user_login(request):
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request=request, user=user) <- This line
return render(request, 'site/homepage.html') <- Or this line
else:
return render(request, 'site/login.html', {'incorrect': True})
else:
return render(request, 'site/login.html', {})
In login.html:
{% block content %}
{% if user.is_authenticated %}
<div class="title">
<h2>Error</h2>
</div>
<p>You have already logged in, {{ user.firstname }}. Please logout to login as another user!</p>
{% else %}
<div class="title">
<h2>Login</h2>
</div>
{% if incorrect %}
<p>You have entered the wrong username and/or password.<br />
Please try again</p>
{% elif unauthorised %}
<p>You must login before trying to access that page!<br /></p>
{% endif %}
<form id="login_form" method="post" action="#">
{% csrf_token %}
<label>Username: <input type="text" name="username" value="" size="50" /></label>
<br />
<label>Password: <input type="password" name="password" value="" size="50" /></label>
<br />
<input type="submit" value="submit" />
</form>
{% endif %}
{% endblock %}
In the form, the action attribute doesn't have any value so you don't send anything to the view. It should be "."
<form id="login_form" method="post" action=".">
or
<form id="login_form" action="{% url 'login' %}" method="post">
if your login url name is login.
Tested in my server this work, if not, tell us the new error.
view.py:
def login_user(request):
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return HttpResponseRedirect('/')
else:
return render(request, 'login/auth.html', {'incorrect': True})
else:
return render(request, 'login/auth.html', {})

Categories