I am currently trying to host a simple login form on a2hosting using Flask but im having issues with urls redirecting and stacking on top of each other.
For example I have www.site.com/index ask for a login or to create one. but when a user logs in or tries to register, the url will do something like www.site.com/login/index instead of just redirecting to /index
Here is a snippet from my routes code
#app.route('/register', methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = RegistrationForm()
if form.validate_on_submit():
#submit to database
return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form)
route snippet
#app.route('/')
#app.route('/index')
def index():
# variable containing a test text
return render_template('home.html', title='Home')
Please send code snippet for index routing - #app.route('/index') ...
Related
I have a small app with flask.
I want to connect it to keycloak server using docker-compose
here is the main code:
keycloak = KeycloakOpenID(server_url='http://localhost:8080/auth/',
client_id='guess-app',
realm_name='guess',
client_secret_key='')
# Define views
#app.route('/')
def index():
if keycloak.token:
return redirect('/home')
else:
return (keycloak.auth_url())
#app.route('/logout')
def logout():
keycloak.logout()
return redirect('/')
# Handle redirect from Keycloak
#app.route('/callback')
def callback():
keycloak.callback()
return redirect('/home')
and here is the screenshot from the client page in keycloak:
screenshot
the connection didn't work and im not getting the login screen and I really don't understand why
I'm using flask and mongodb, I have a user table where it has a boolean attribute is_admin and I want to make specefic views and routes accessible only for admin users, I have read about Flask-admin and Flask-Principal but they seemed complicated to me since I am very beginner and its just a school project, is there a way to achieve that without using Flask-Principle?.
for example I want only admin to access this route
#users.route('/add', methods=['GET', 'POST'])
#login_required
def add():
form = UserForm(request.form)
if request.method == 'POST':
if form.validate():
user = User(username=form.username.data, password= generate_password_hash(form.password.data), vorname=form.vorname.data, nachname=form.nachname.data, geburtsdatum=form.geburtsdatum.data, email=form.email.data, admin=form.admin.data, aktiv=form.aktiv.data)
user.save()
flash("user added successfully.", "success")
return redirect(url_for('.index'))
return render_template('form.html', users=users, form=form, info=session)
If I understand your question correctly, something like this might be what you're looking for:
from flask_login import current_user
# use the suggested pattern to login user then..
#users.route('/add', methods=['GET', 'POST'])
#login_required
def add():
if not current_user.is_admin:
abort(403)
# rest of your route
This will return HTTP 403 - Forbidden
as per wikipedia:
The HTTP 403 is a HTTP status code meaning access to the requested resource is forbidden. The server understood the request, but will not fulfill it.
i followed miguel grinberg tutorial and now i'm applying what i learned in a side project but in all cases i came a cross some problem which i ignored at first and thought it is my mistake but after investigation i can't find why this behavioud happens, the problem is when i try to go to any url within the website while not logged on log-in screen comes but after that the original requested page is not loaded successfully and flask throughs BuildError exception.
below is my code samples
#app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username= form.username.data).first()
if user is None or not user.check_password(form.password.data):
return redirect(url_for('login'))
login_user(user)
next_page = request.args.get('next')
if not next_page or url_parse(next_page).netloc != '':
return redirect(url_for('index'))
return redirect(url_for(next_page))
return render_template('login.html', form=form)
as you can see i'm getting next parameter and doing some security checks if it exists then redirecting to next_page url , but what happens is that there is build error, for exmpale something like the following
BuildError: Could not build url for endpoint u'/user/4556'. Did you mean
'user' instead?
while user view function looks like this
#app.route('/user/<username>', methods=['GET'])
#login_required
def user(username):
....
Instead of
return redirect(url_for(next_page))
you probably want
return redirect(next_page)
Your "next" parameter would look like "/user/4556" but you don't have an endpoint called "/user/4556", so you don't want to pass that to url_for. Passing the string directly to redirect will suffice.
I am writing a simple flask app using flask-login and flask-mongoengine, everything was working fine until I updated all of the python plugins that I need for the project. Now flask won't log me in. When I login and the form is validated, it returns me to the login page, with the url: http://localhost:5000/auth/login?next=%2Findex ... I think the %2F might have something to do with the issue.
Here is my login view:
#bp.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = LoginForm()
if form.validate_on_submit():
user = User.objects(username__exact=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash(_('Invalid username or password'))
return redirect(url_for('auth.login'))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get('next')
if not next_page or url_parse(next_page).netloc != '':
next_page = url_for('main.index')
return redirect(next_page)
return render_template('auth/login.html', title=_('Sign In'), form=form)
I'm using WTForms and I can confirm that the form action=""
This is adapted from the flask megatutorial, but I'm using MongoDB.
Problem solved!
When I was converting the app from using SQL to MongoDB, I incorrectly made the load_user function like:
#login.user_loader
def load_user(username):
return User.objects(username__exact=username).first()
But in reality the load_user function needs to accept the id field as an interface, so the function should look like:
#login.user_loader
def load_user(id):
return User.objects.get(id=id)
What are the options when you want to return the user to the same page in Django and what are the pros/cons of each?
Methods I know:
HTTP_REFERER
GET parameter containing the previous URL
Session data to store the previous URL
Are there any other?
One of the way is using HTTP_REFERER header like as below:
from django.http import HttpResponseRedirect
def someview(request):
...
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
Not sure of cons of this!
100% working Example
For Class Based View and Function:
from django.http import HttpResponseRedirect
...
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
or
from django.http import HttpResponseRedirect
...
return HttpResponseRedirect(self.request.META.get('HTTP_REFERER'))
Example -
class TaskNotificationReadAllView(generic.View):
def get(self, request, *args, **kwargs):
TaskNotification.objects.filter(assigned_to=request.user).update(read=True)
print(request.META.get('HTTP_REFERER'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
While the question and answer is old, I think it's lacking a few options. I have not find any cons with the methods, I would be happy to know if there are any?
request.path_info
request.get_full_path()
request.build_absolute_uri()
from django.shortcuts import redirect
redirect(request.path_info) # No query parameters
redirect(request.build_absolute_uri()) # Keeps query parameters
redirect(request.get_full_path()) # Keeps query parameters
In django view suppose you are not logged in but click on some content that content trigger some url like /board/2/new_topic then #login_required will redirect you to login page with this url
http://localhost:8000/signin/?next=/boards/2/new_topic/
so our aim is redirect to http://localhost:8000/boards/2/new_topic/ page after successful login so one line we will have to add
if 'next' in request.GET:
return redirect(request.GET['next'])
then if it next is there then it will redirect according to that other normal redirect .
Views.py :
def signin(request):
if request.method == "POST":
user_login_form = UserLoginForm(request.POST)
email = request.POST['email']
password = request.POST['password']
user = authenticate(request, email=email, password=password)
if user and user.is_active:
login(request, user)
if 'next' in request.GET:
return redirect(request.GET['next'])
else:
return redirect('home')
else:
return render(request, 'signin.html', context={'form': user_login_form})
else:
user_login_form = UserLoginForm()
return render(request, 'signin.html', context={'form': user_login_form})