I'm pretty new to asking questions on stack overflow and building a web app with flask so I apologize in advance if I say something that's incorrect.
I'm building a flask web app that handles scheduling appointments and naturally i'm using 3rd party libraries/wrappers to make API calls and to handle db queries (sqlite). As it is currently, my app doesn't use any kind of async code. I got thinking about scenarios where multiple users try to login or book an appointment, both involving db queries and api calls, and whether my application will block or not. Given that its all synchronous, if multiple users do try and login and book an appointment, will it block for some users while it handles other user requests, or is that all independent of my flask app and dependent on the WSGI server running the app? Any tips on how I can improve the performance of my app with regards to handling multiple requests?
Example route that multiple users try to visit at the same time:
...
#app.route('/signup/')
def signup():
# has a form that takes user input and submits it for processing in process_signup()
return render_template('signup.html')
#app.route('/process_signup/', methods=['POST'])
def process_signup():
form = request.forms
username = form['username']
password = form['password']
# insert values into customer db in a synchronous fashion
db = db() #gets the database
cursor = db.execute('insert into customers (username, password) values (?,?)', [username, password])
db.commit()
#send out a verification email using email api without any async
email_new_customer()
return redirect(url_for('signin'))
NOTE: I read that its better to have db queries and api calls handled asynchronously but not sure where to start or what kind of library compatible with flask will help me achieve that.
Thank you for your help and again I may have a big misunderstanding of how it all works as i'm very to new to this so I apologize.
Related
I'm having concurrency problems leading to PK violations in flask-sqlalchemy with MySQL using uwsgi with two worker threads and nginx.
I'm using keys that come from the payload. If the contact comes in with a key that exists in the database, update the record, if not, create a new record.
Here is the setup and what I think is happening.
#project/__init__.py
app = Flask(__name__)
db = SQLAlchemy(app)
from project import views, models
#project/views.py
from project import db
#app.route('/receive', methods = ['POST'])
def receive():
#Check to see if the contact exists in the database
contact = models.Contact.getIssue(contact_payload['id'])
if contact is None:
#If not in the DB, create a new contact
new_contact = models.Contact(contact_payload)
db.session.merge(new_contact)
else:
#If in the DB, create an updated representation of this contact
updated_issue = contact.updateContact(contact_payload)
db.session.merge(updated_issue)
...Some other stuff...
#Commit to DB
db.session.commit()
#Respond
resp = jsonify({'Result' : 'Success'})
resp.status_code = 200
return resp
The issue comes when we receive two requests for the same contact at the exact same time (requestA is 12:10:49,063 and requestB is 12:10:49,066). One of the requests ends in a PK violation.
I suspect they're coming in on different worker threads and each request gets a scoped session (sessionA - requestA and sessionB - requestB) from flask-sqlalchemy.
I suspect both sessions contain nothing at the beginning of the requests that are now in the above code flow simultaneously.
requestA goes through the appropriate code flow and merges new_contact into sessionA.
At the same time requestB goes through the same code path where contact is None (because sessionA hasn't committed yet) and merges new_contact into sessionB.
Then sessionA commits before sessionB. When sessionB goes to commit, it gets the PK violation.
Can we do anything else other than catch the PK violation and react accordingly?
You have two options:
Catch the PK violation and react accordingly, like you already said.
Lock your transaction based on your id: this is more complicated, you need something to synchronize your locks, like redis. Take a look at python-redis-lock. It is just one option, the solution here is to avoid concurrency for a PK.
https://pypi.python.org/pypi/python-redis-lock
I work on my simple blogging system written in Python, Flask and SQLite,
and I've created a simple authorization system for it. There is no need for anything fancy, so it's just a matter of sending login and password through a form and setting a flag in Flask's session. I wanted to know how things like this are done, so I didn't use any modules.
I'm wondering if this method is correct and secure just enough.
# from auth module
#auth.route('/login', methods=['POST'])
def login():
"""Login as blog admin."""
# Successeful login conditions
user_is_valid = request.form['user'] == current_app.config['USER']
password_is_valid = request.form['password'] == current_app.config['PASSWORD']
trap_is_empty = not request.form['trap']
# Login user if credentials are correct
if user_is_valid and password_is_valid and trap_is_empty:
session['is_admin'] = True
return redirect(url_for('admin.posts_page'))
else:
return render_template('auth.html')
# from admin module
#admin.before_request
def before_request():
""" Before any request check admin flag, redirect to the main page if there is none. """
if not session.get('is_admin'):
return redirect(url_for('blog.index_page'))
proj.db.connect()
It honestly looks fine for just a basic authentication system. The bad part is storing the credentials in the config.
If you want to get all cool and fancy, you can use itsdangerous to generate hashes and salts of passwords and store them in your sqlite database.
Typically, you'd have a table with id, username, password, and a boolean flag like "is_admin" or something that you can check when you authenticate.
So, it's fine for some playing around, but I wouldn't recommend anything like this in production.
I'm new to EVE framework, but already have some experience with flask and mongodb. I want to build a web app based on eve rest with token auth. So for example I have the case: I want to check if email exists in realtime when user filled out the form. The user info is in users collection, but I want to put users collection under token auth. So how should I handle custom request without token? Should it be handled through flask?
Maybe something like this:
#app.route('/_check_email', methods=['GET'])
def check_email():
print request
email = request.args.get('email', 0, type=str)
accounts = app.data.driver.db['users']
lookup = {'email': email}
account = accounts.find_one(lookup)
if not account:
return jsonify(valid=True)
else:
return jsonify(valid=False)
Thanks!
You might want to wrap it all in a Flask Blueprint. See what's been done with Eve-Docs extension. Other than that, Eve is just a Flask subclass so you are free to play with it as you would do with Flask itself.
My company has a Flask application that uses flask-login to handle user logins/logouts and sessions. We use the #login_required decorator to protect views. Our clients log via persistent users stored in a database. However, we want employees of our company to be able to log in to our clients' sites without popping up in their users lists. We verify our own authenticity by CAS login at our own CAS server and checking that the username belongs to our company.
We want the employees to simply be able to login without needing to be persisted in the database but flask-login requires a persisted user model.
Sorry for the troublesome use of words here, but I hope this is understadable.
Every authorization system should check user in some storage by some field and in usual cases return exist or has permisions.
So with flask-login you can implement it with next: user_loader/header_loader/request_loader and UserMixin with user_id.
Every request with login_required call *_loader to get UserMixin. So it can look like next:
#login_manager.request_loader
def loader(request):
identifier = get_identifier_from_request(request)
exist = check_on_cas_server(identifier)
if not exist:
return None
user = UserMixin()
user.id = get_specified_or_random_id(identifier, exist)
return user
Details you can found with https://flask-login.readthedocs.org/en/latest/.
I'm writing a web app which has a page for admin tasks. One of the tasks is that the admin users must be able to edit other users details. Alas, I've fallen at quite a simple roadblock.
I've set up a very simple jQuery AJAX Get request, successfully transferring a string to the server and back. This is just background, but not the issue. The issue lies in retrieving other user's objects.
At the moment, with a username I know exists, this code which is accessed in views.py, produces a 500 Internal Server Error.
#login_required
def user_edit_getuser(request):
# Like before, get the request's context.
context = RequestContext(request)
inputname = request.GET['inputNameSend']
user_obj = User.objects.get(inputname)
return HttpResponse(inputname) #later will return a JSON String
get takes keyword arguments only: the key is the field to look up.
user_obj = User.objects.get(username=inputname)
Also, you should probably deal with the possibility that the GET request has no inputNameSend key.
For JS development, you can usually see the error page in the Chrome dev tools/Firebug console in the Network tab.