Passing data into flask template - python

During login form validation, I query for a user and store the object on the form instance. I want to pass the user object into the template. Following Python, Flask - Passing Arguments Into redirect(url_for()) , I tried:
def home():
form = LoginForm(request.form)
# Handle logging in
if request.method == 'POST':
if form.validate_on_submit():
login_user(form.user)
flash("You are logged in.", 'success')
redirect_url = request.args.get("next") or url_for("user.profile")
return redirect(redirect_url, userobj=form.user)
I'm redirecting to :
#blueprint.route("/profile")
#login_required
def profile():
return render_extensions("users/profile.html")
and again I want to pass the user object into profile.html template.
I'm getting:
TypeError: redirect() got an unexpected keyword argument 'userobj'
How can I fix this?

You may not be doing it correct. user which is logged in is available through current_user which is available in from flask.ext.login import current_user
this is how i did
#auth.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is not None and user.verify_password(form.password.data):
login_user(user, form.remember_me.data)
return redirect(request.args.get('next') or url_for('main.index'))
flash('Invalid username or password')
return render_template('auth/login.html', form=form)
in the index view i am able to access it like current_user.username same in the template
try this it may help
peace

Related

How to prevent a client to resubmit form data to a flask login route?

#app.route("/login", methods=["GET", "POST"])
def login():
form = LoginForm()
if form.validate_on_submit():
if login_check(form.email.data, form.password.data):
session["email"] = form.email.data
return redirect(url_for("login"))
flash("Wrong email or password")
if session.get("email"):
return redirect(url_for("index"))
return render_template("login.html", form=form)
If the user submits invalid information, then no redirect occurs and when the page is refreshed, the information is sent again. How can I prevent it using post/redirect/get?
I tried to add an additional condition to redirect the page if the user entered wrong information, but then return render_template("login.html", form=form) is never executed

werkzeug.routing.BuildError: Could not build url for endpoint 'login' with values ['next']. Did you mean 'core.login' instead?

url_for points to a valid view still getting the below error. I have tried adding the else block to mitigate the error as well but somehow same error is reported.
werkzeug.routing.BuildError: Could not build url for endpoint 'login'
with values ['next']. Did you mean 'core.login' instead?
The code:
from ..extensions import ldap
from .forms import LoginForm
core = Blueprint('core', __name__)
#core.route('/')
#ldap.login_required
def index():
return render_template('index.html')
#core.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
if g.user:
return redirect(url_for('index'))
if request.method == 'POST':
user = request.form['user']
passwd = request.form['passwd']
test = ldap.bind_user(user, passwd)
if test is None or passwd == '':
return 'Invalid credentials'
else:
session['user_id'] = request.form['user']
return redirect('/')
return render_template('sign-in.html', form=form)
#core.route('/logout')
def logout():
session.pop('user_id', None)
return redirect(url_for('index'))
I am using python 3.8 and flask 2.0.2.
This is expected behavior since your login endpoint is part of your core blueprint. When using url_for you should use route endpoint name rather than view function name:
url_for('core.login')
As the exception suggests.
If you need to customize what the endpoint is called you can do it like so:
#core.route('/login', methods=['GET', 'POST'], endpoint='my_login')
...
url_for('core.my_login')
And if there's any confusion you can always inspect app.url_map to see what routes are defined and what are their endpoint names.

Customized debug/flask Flask python

I have created an webapp.The home page consists of a login form and upon login it will redirect to "host_address/security_portal". And once I logout I tried accessing this security_portal page it says
could not build url for endpoint 'login'. Did you mean 'logout' instead
what I want is a customized error page instead of this debug page.
#app.route('/', methods=['GET', 'POST'])
def home():
form = LoginForm()
if form.validate_on_submit():
# Grab the user from our User Models table
user = User.query.filter_by(email=form.email.data.lower()).first()
if user==None:
flash('The E-mail is not registered! Kindly register and login')
return redirect(url_for('home'))
if user.check_password(form.password.data) and user is not None:
#Log in the user
login_user(user)
next = request.args.get('next')
#check if user trying to access page that needs login without signing in#
if next == None or not next[0]=='/':
next = url_for('security')
return redirect(next)
else:
flash("Incorrect Password!")
return render_template('home.html',form=form)
#app.route('/SecurityPage')
#login_required
def security():
return render_template('SecurityPage.html',username=(current_user.email.split('#'))[0].split('.')[0].capitalize())

AttributeError: 'dict' object has no attribute 'is_active' (PyMongo And Flask)

#app.route("/register", methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
users = mongo.db.users
hash_password=bcrypt.generate_password_hash(form.password.data).decode('utf-8')
eml=form.email.data
gen=form.gender.data
ctry=form.country.data
profile={'name' : form.username.data, 'password' :hash_password,'email':eml,'gender':gen,'country':ctry}
users.insert(profile)
#users.insert({'name' : form.username.data, 'password' :form.password.data})
flash(f'Your has been Account created for Username {form.username.data}!, You can login', 'success')
return redirect(url_for('login'))
#return redirect(url_for('home'))
return render_template('register.html', title='Register', form=form)
#app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
users = mongo.db.users
loginuser = users.find_one({'email' : form.email.data})
if loginuser and bcrypt.check_password_hash(loginuser['password'],form.password.data):
#if form.email.data == 'admin#blog.com' and form.password.data == 'password':
login_user(loginuser,remember=form.data.remember)
return redirect(url_for('home'))
#flash('You have been logged in!', 'success')
#return redirect(url_for('home'))
else:
flash('Login Unsuccessful. Please check username and password', 'danger')
return render_template('login.html', title='Login', form=form)
I have created a simple register and login method using flask with combination of pymongo.
Now for user session management i am using flask_login
but it gives me this error
AttributeError: 'dict' object has no attribute 'is_active'
the solution that i found different post was to add UserMaxIn in UserClass
but i dont have any class for User Model and i dont want to make it either
what would be the solution of this error ?
Flask-Login requires that you use a class to represent users, not a raw dict.
As described in documentation, this class needs to implement some properties and methods, included the is_active() method.
The UserMixin class is the base class that provides default implementations for all the required properties and methods and you can extend it and create a simple User class.
Update: added example
Based on what you already have, the simplest thing you can do is:
create a custom User class that extends UserMixin
store the json object from MongoDB inside the User class
override the methods for which you require a behavior different from the default one
In the /login route create an instance of the User class and pass it to flask_login.login_user()
User class
class User(UserMixin):
def __init__(self, user_json):
self.user_json = user_json
# Overriding get_id is required if you don't have the id property
# Check the source code for UserMixin for details
def get_id(self):
object_id = self.user_json.get('_id')
return str(object_id)
For all the methods/properties (is_authenticated, is_active, is_anonymous), except get_id it uses the default implementations. If you don't need the default implementations you don't need to extend UserMixin but you have to implement all the methods by yourself.
Usage of the User class in login route
#app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
users = mongo.db.users
loginuser_json = users.find_one({'email': form.email.data})
if loginuser_json and bcrypt.check_password_hash(loginuser_json['password'], form.password.data):
# Create a custom user and pass it to login_user:
loginuser = User(loginuser_json)
login_user(loginuser, remember=form.data.remember)
return redirect(url_for('home'))
else:
flash('Login Unsuccessful. Please check username and password', 'danger')
return render_template('login.html', title='Login', form=form)
Remember that you also have to provide a user_loader as described here. For example, given the user_id, perform a query on MongoDB and return the User object:
#login_manager.user_loader
def load_user(user_id):
users = mongo.db.users
user_json = users.find_one({'_id': ObjectId(user_id)})
return User(user_json)
Useful links
Flask-Login documentation
UserMixin source code
A more complete User class

Flask doubts regarding redirection

I am following this tutorial here. The login page shows a sign in page. When I click on any of the providers, and click on the submit button, the page gets redirected back to the login page. What am I doing wrong here? I have the following code in the views.py page
#app.route('/login', methods=['GET', 'POST'])
#oid.loginhandler
def login():
if g.user is not None and g.user.is_authenticated():
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
session['remember_me'] = form.remember_me.data
return oid.try_login(form.openid.data, ask_for=['nickname', 'email'])
return render_template('login.html',
title='Sign In',
form=form,
providers=app.config['OPENID_PROVIDERS'])
#oid.after_login
def after_login(resp):
if resp.email is None or resp.email=="":
flash('Invalid login. Please try again')
return redirect(url_for('login'))
user=User.query.filter_by(email=resp.email).first()
if user is None:
nickname= resp.nickname
if nickname is None or nickname == "":
nickname=resp.email.split('#')[0]
user= User(nickname=nickname, email=resp.email)
db.session.add(user)
db.session.commit()
remember_me=False
if 'remember_me' in session:
remember_me=session['remember_me']
session.pop('remember_me', None)
login_user(user, remember = remember_me)
return redirect(request.args.get('next') or url_for('index'))
you need to set the app config
app.config['SECURITY_POST_LOGIN_VIEW'] = '/post_login_page'
app.config['SECURITY_POST_REGISTER_VIEW'] = '/register_complete'

Categories

Resources