Flask render_template context not showing in URL - python

I am trying to pass params to the URL in flask, but I can not get them to show up for anything.
#logout.route('/logout')
def logout_page():
current_provider = current_oauth_user.get_provider()
return render_template('index.html', provider=current_provider)
I expect to see /logout?provider=facebook but I just get /logout
Right now I am doing this:
#logout.route('/logout')
def logout_page():
provider = request.args.get('provider')
current_provider = current_oauth_user.get_provider()
if not provider and current_provider:
return redirect(url_for('logout.logout_page',
provider=current_provider))
return render_template('index.html')
but that just seems so terrible.

You should return some value using '/logout' path.
So at first, you use render_template(index.html) under def main(). Then you create def logout_page() and return some value ( in your case is current_provider).
#app.route('/')
def main():
return render_template('index.html')
#app.route('/logout')
def logout_page():
current_provider = current_oauth_user.get_provider()
return current_provider
if __name__=="__main__":
app.run(port=8000)

Related

Python | check if dict{} item is in list[]

Attempting to check an in-memory list, plant_list[] against a JSON payload from an api.
If the incoming payload's dict name matches inside of plant_list the if should fire off.
Instead my script only returns null
Please point out my mistakes.
The JSON sent over the api call is:
{ "name":"swizz", "days": "7", "price": 2.00 }
Source Code
from flask import Flask, request
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
#app.route('/', methods=['GET', 'POST'])
def home():
return 'Tiny'
plant_list = []
class Plant(Resource):
def get(self, name):
return {'Name':name}, 200
def post(self, name):
payload = request.get_json()
for x in range(0, len(plant_list)):
if payload['name'] == plant_list[x]['name']:
return {'message': f'''Item {payload['name']} already stored in database.'''}
else:
plant_list.append(payload)
return plant_list, 201
api.add_resource(Plant, '/plant/<string:name>')
if __name__ == '__main__':
app.run(port=9004, debug=True)
You can test for key in dict simply by: if key_name in my_dict:... So, if "price" in plant_list[x]:
You are setting plant_list as a global. If you want to use that inside a Class, you should define it inside the function in your class:
plant_list = []
class Plant(Resource):
....
def post(self, name):
global plant_list
....
Not sure why you need it as a global variable. Perhaps you want:
class Plant(Resource):
plant_list = []
....
def post(self, name):
....

redirecting on flask from a 'POST' route to a 'GET' route

I want to redirect to another url( of a route whose method by default is 'GET') from a route whose method has been set to 'POST' if some condition is met. The 'GET' route gets called when I check from the terminal, but the redirection doesn't happen from the browser. Am doing this in flask using 'url_for'. Any help?
I've tried using the _method parameter in the url_for ,i.e, return redirect(url_for('second', _method='GET')
Here's some code:
#app.route('/first', methods=['POST'])
def first():
some_data = request.get_json(force=True)
if some_data is None:
return redirect(url_for('second', _method='GET'))
session['data_to_use'] = some_data
return jsonify(some_data)
#app.route('/second')
def second():
return render_template('second.html')
This is what I get on the terminal:
"POST /first HTTP/1.1" 302 -
"GET /second HTTP/1.1" 200 -
Are you sure your "some_data" value is None? Redirect usually should work just with ordinary url_for usage even if you are redirecting from post to get, like this:
#app.route('/first', methods=['POST'])
def first():
some_data = request.get_json(force=True)
if some_data is None:
return redirect(url_for('second'))
session['data_to_use'] = some_data
return jsonify(some_data)
You can just return the name of the function that renders the template
#app.route('/first', methods=['POST'])
def first():
some_data = request.get_json(force=True)
if some_data is None:
return second()
session['data_to_use'] = some_data
return jsonify(some_data)

Similiar routes/pages in Flask - how to remove duplication

I have got a few subpages which look very similiar:
They are almost the same but each of them presents different currency:
#app.route('/', methods=['POST', 'GET'])
#app.route('/dollar', methods=['POST', 'GET'])
def dollar_page():
form = MyTextForm()
if form.validate_on_submit():
values = app.process(request.form["values"])
labels = get_data()
return render_template('currency.html', currency="dollar", labels=labels, values=values)
#app.route('/euro', methods=['POST', 'GET'])
def euro_page():
form = MyTextForm()
sentiment = ""
if form.validate_on_submit():
values = app.process(request.form["values"])
labels = get_data()
return render_template('currency.html', currency="euro", labels=labels, values=values)
#app.route('/pound', methods=['POST', 'GET'])
def pound_page():
... etc ...
What is the best way to get rid of this duplication in Flask applications? Is there any pattern? Thanks!
Create a variable in your route to receive the type of currency. The route variable is passed as an argument to the view function. The / route doen't have the variable, so provide a default in that case.
import functools
def verify_currency(f):
#functools.wraps(f)
def wrapper(currency_type):
if currency_type not in ['dollars', 'euros']: #can add more currencies to list later
return flask.render_template("error.html") #or redirect
return f(currency_type)
return wrapper
#app.route('/', methods=['POST', 'GET'], defaults={'currency': 'euro'})
#app.route('/currency/<currency>', methods=['POST', 'GET'])
#verify_currency
def dollar_page(currency):
form = MyTextForm()
values = labels = None
if form.validate_on_submit():
values = app.process(request.form["values"])
labels = get_data()
return render_template('currency.html', currency=currency, labels=labels, values=values)

Flask-restful basic Authentication

I am new to Flask and I need some help for my school work.
I am trying to build a simple ToDo list system using flask-restful.
My current code looks like this:
class ToDoList(Resource):
'''TODO LIST'''
operation = ['delete']
decorators = [auth.login_required, advertise('operation')]
def post(self):
"""remove all item in the TODO list"""
operation = request.args.get('op')
if operation == 'delete':
collection2.delete_many({})
return {'Success': 'OK'}, 200
return {'Error':'Illegal Operation'}, 400
def get(self):
"""return a list of the TODO name"""
list_1 = collection2.find()
list_2 = []
for each in list_1:
list_2.append(JSONEncoder().encode(each))
return {'list':list_2}, 200
It works, but I want only the post method to require authentication, and get method without authentication so anyone can acquire the list without login. I am using the flask-restful I don't know how to give the decorators separately to each function.
I used flaskrestplus to do basic authentication. All the required authorizations are provided as an authorizations dictionary. Then they are passed to the API.
Also the authorizations can be applied at the method level using
#api.doc(security='basicAuth')
The validation logic (can be ldap validation or db validation) can be writted in a decorator called requires_Auth. This decorator is invoked using
decorators = [requires_Auth]
Complete code
from flask import Flask, request
from flask_restplus import Api, Resource
from functools import wraps
def requires_Auth(f):
#wraps(f)
def decorator(*args, **kwargs):
auth = request.authorization
if auth:
print "inside decorator", auth.username,auth.password
return f(*args, **kwargs)
else:
return "Login required!!!!",401
return decorator
authorizations = {
'basicAuth': {
'type': 'basic',
'in': 'header',
'name': 'Authorization'
}
}
api = Api(app, version='1.0',
authorizations=authorizations
)
ns = api.namespace('/', description='Authentication API')
#ns.route('/withDecorator')
class HelloWorldWithDecorator(Resource):
decorators = [requires_Auth]
#api.doc(security='basicAuth')
def get(self):
return {'hello': 'world'}
api.add_namespace(ns)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5001)
From Flask-RESTful documentation [1]:
Alternatively, you can specify a dictionary of iterables that map to HTTP methods and the decorators will only apply to matching requests.
def cache(f):
#wraps(f)
def cacher(*args, **kwargs):
# caching stuff
return cacher
class MyResource(restful.Resource):
method_decorators = {'get': [cache]}
def get(self, *args, **kwargs):
return something_interesting(*args, **kwargs)
def post(self, *args, **kwargs):
return create_something(*args, **kwargs)
In your case it would be:
method_decorators = {'post': [auth.login_required]}

How to pass a list to #app.route(/<list>)

Is it possible to pass a python list in #app.route to define the accepted routes?
I can't find a way to do it :\
Here is what I am trying to do exactly:
urilist = ["/log", "/login", "/loginexample"]
#app.route('/<urllist>', methods=['GET'])
def main():
return 'Hello World!'
I would like all the route in the list to redirect to the same function.
Thank you!
You can pass the parameter from the route to the function, and check if it exists in the list:
urilist = ["/log", "/login", "/loginexample"]
#app.route('/<urllist>', methods=['GET'])
def main(urllist):
if "/{}".format(urllist) in urilist:
return 'Hello World!'
return flask.render_template("error.html")#or whatever else you would do if urllist is not in urilist

Categories