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

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

Related

Trying to test a function but in test it returns None?

I Have this function that I wish to test, this is how it looks like.
def myfunction():
response = requests.post(url,params=params,headers=headers,data=data)
response = response.json()
return response["Findme"].lower()
My test script:
#mock.patch('requests.post',return_value="{'Findme': 'test'}")
def test_myfunction(mocked_post):
**assert myfunction() == "test"**
When i run the test, i keep getting None for myfunction(), but when i remove the response.json() it works?
Please can anyone assist me.
As mentioned by Deep Space, your returned object does not have a json method, as it is of type str. If you want to have the same behavior as in the tested function, you have to provide an object with that method:
class MockResponse:
"""Mocks relevant part of requests.Response"""
def __init__(self, s):
self.json_string = s
def json(self):
return json.loads(self.json_string)
#mock.patch("requests.post", return_value=MockResponse('{"Findme": "test"}'))
def test_myfunction(mocked_post):
assert myfunction() == "test"
This way, an object of type MockResponse is returned from the mocked post function, that can be deserialized using json().
You could also mock the return value of json directly instead of mocking the return value of post, if you want to do this. In this case you wouldn't need an extra class:
#mock.patch("requests.post")
def test_myfunction(mocked_post):
mocked_post.return_value.json.return_value = {"Findme": "test"}
assert myfunction() == "test"

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):
....

How to pass two variables to a function with decorator

I have a function ('postcode') that takes input from user and generates two variables that I want to pass to another function ('constituency').
How can I pass two arguments between function such that only one is passed to the url?
app("/postcode", methods=["GET", "POST"])
def postcode():
form = PostcodeForm()
if form.validate_on_submit():
pc = form.postcode.data.replace(" ", "").strip()
if validate(pc) == True:
code, const = dosomething(pc)
return redirect(url_for('app.constituency', const_id=const)), code
return render_template("template1.html", form=form)
#app.route("/constituency/<string:const_id>")
def constituency(const_id):
const = const_id
people = People.query.filter_by(code=code) # I want the value of "code" here to come from the function 'postcode' above
return render_template("template2.html", people=people, const=const)
You either need to pass code as a query parameter, or make a new url route that takes a code parameter, url_for doesn't calls consitutency directly, it just generates a url that the browser then requests.

Flask render_template context not showing in URL

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)

My python function won't write to a file

I've made a function for a flask application to create a decorator and a function and then write them to a file but when I run it, it doesn't create a file and write to it and it doesn't return any errors.
def make_route(title):
route = "#app.route(/%s)" %(title)
def welcome():
return render_template("%s.html" %(title))
return welcome
f = open('test1.txt', 'w')
f.write(route, '/n', welcome, '/n')
f.close()
make_route('Hi')
A return statement terminates execution of the function, so any code after it is ignored. Also, write writes a string, not random objects. You want:
def make_route(title):
route = "#app.route(/%s)" %(title)
def welcome():
return render_template("%s.html" %(title))
with open('test1.txt', 'w') as f:
f.write('%r\n%r\n' % (route, welcome))
return welcome
make_route('Hi')
I would use philhag answer but use %s instead of %r or you'll write a string, and you could use .name if you want to use the function more than once(Which you probably do).
def make_route(title):
route = "#app.route('/%s')" %(title)
def welcome():
return render_template("%s.html" %(title))
with open('test2.py', 'w') as f:
f.write('%s\n%s\n' % (route, welcome))
welcome.__name__ = title
return welcome
make_route('Hi')

Categories