In this article — a continuation of Part 1 — I’ll cover some more advanced topics I previously mentioned. To begin, we’ll implement a simple login/register system where clients can register, log in using their credentials, and check their profile. So, let’s get started!
Flask Global Variables
Flask provides several global variables that can simplify your development workflow. For example, the request object is a global variable that stores data related to HTTP requests — such as URL, query parameters, headers, and more.
You can import Flask global variables in two ways:
from flask import globals # imports all global varsOr, if you only need specific ones (recommended for cleaner code):
from flask import requestTo see how we can access incoming data, let’s create a simple /test route:
@app.route('/test', methods=['GET'])def test(): name = request.args.get('name') username = request.args.get('username') password = request.args.get('password') return f"Hello, {name}! Your username is {username} and your password is {password}"This route accepts only GET requests. You can access the parameters sent by the client via request.args.get('field_name').
For example, accessing this URL:
http://localhost:5000/test?name=Armin&username=mynameisarmin&password=mysafepasswordWill return:
Hello, Armin! Your username is mynameisarmin and your password is mysafepasswordWays to Access Request Data
request.data: raw data as a string when Flask can’t handle the mimetype.request.args: key/value pairs in the query string.request.form: key/value pairs in the request body (e.g. from HTML forms).request.files: uploaded files.request.values: combinesargsandform, preferringargsif duplicate keys exist.request.json: parsed JSON data (must haveContent-Type: application/json).
These objects are typically instances of MultiDict, except for request.json.
You can access values with:
request.form['name']: use this if you’re sure the key exists.request.form.get('name'): safer if the key might not exist.request.form.getlist('name'): use this if the same key is submitted multiple times.
TinyDB
To build the login/register system, we need a way to store user credentials. Rather than using a full-fledged database like MongoDB or Redis for this small demo, we’ll use TinyDB, a lightweight, document-oriented database that stores data in a JSON file.
“TinyDB is a document-oriented database that stores data in a JSON file. It’s the closest thing I’ve found to a NoSQL version of SQLite. It’s simple, lightweight, serverless, and extensible.” — lyz-code.github.io
To install TinyDB:
pip install tinydbWe’ll also write a helper class to simplify using TinyDB. Create a file called db.py with the following content:
from tinydb import TinyDB, Queryimport os
class Database: def __init__(self, dbName, dbPath): self.dbName = dbName self.dbPath = dbPath if dbPath.endswith('/') else dbPath + '/' self._initialize_db_path() self.db = TinyDB(self.dbPath + self.dbName, indent=4, sort_keys=True, separators=(',', ':'))
def _initialize_db_path(self): if not os.path.exists(self.dbPath): os.makedirs(self.dbPath)
def query(self, table, query): return self.db.table(table).search(query)
def insert_or_update(self, table, data): table_ref = self.db.table(table) table_ref.upsert(data, Query().id == data['id']) return True
def insert(self, table, data): self.db.table(table).insert(data) return True
def close(self): self.db.close()Then import your helper and Flask’s jsonify in your main file:
from db import *from flask import jsonifyCreate the database instance after initializing your Flask app:
app = Flask(__name__)myDatabase = Database('db.json', 'database/')Register Route
@app.route('/register', methods=['POST'])def register(): name = request.json['name'] username = request.json['username'] password = request.json['password']
if myDatabase.query('users', Query().username == username): return jsonify({"error": "Account already exists"})
myDatabase.insert('users', {'name': name, 'username': username, 'password': password}) return jsonify({'status': 'success'})This route accepts JSON data, checks if a user with the same username already exists, and if not, inserts the user into the database.
Testing the Endpoint
- For GET requests: just open the URL in your browser.
- For POST requests: use Postman, curl, or online tools like ReqBin.
Tip: Postman is more powerful and user-friendly, but ReqBin is great if you don’t want to install anything.
Login Route
@app.route('/login', methods=['POST'])def login(): username = request.json['username'] password = request.json['password']
user = myDatabase.query('users', Query().username == username and Query().password == password) if user: return jsonify({'status': 'success'}) return jsonify({'error': 'Account does not exist'})JWT Integration
JWT (JSON Web Token) is a secure way to transfer identity and authorization information.
Install the extension:
pip install Flask-JWT-ExtendedImport what we need:
from flask_jwt_extended import create_access_token, get_jwt_identity, jwt_required, JWTManager, verify_jwt_in_requestConfigure your app:
app.config["JWT_SECRET_KEY"] = "super-secret" # Replace with a secure key!jwt = JWTManager(app)You can generate a random key using:
https://random.justyy.workers.dev/api/random/?cached&n=32
Updated Login Route with JWT
@app.route('/login', methods=['POST'])def login(): username = request.json['username'] password = request.json['password']
user = myDatabase.query('users', Query().username == username and Query().password == password) if user: return jsonify({ 'status': 'success', 'token': create_access_token(identity=username) }) return jsonify({'error': 'Account does not exist'})On success, you’ll receive a JWT in the response.
Index Route (JWT Protected)
@jwt_required()@app.route('/index', methods=['GET'])def index(): verify_jwt_in_request() current_user = get_jwt_identity()
if current_user: return jsonify({'status': 'success', 'username': current_user}) return jsonify({'error': 'Invalid token'})Send the JWT token in the
Authorizationheader like:Authorization: Bearer <your-token>
Full Source Code
from flask import Flask, request, jsonifyfrom db import *from flask_jwt_extended import create_access_token, get_jwt_identity, jwt_required, JWTManager, verify_jwt_in_request
app = Flask(__name__)app.config["JWT_SECRET_KEY"] = "super-secret" # Replace this!jwt = JWTManager(app)myDatabase = Database('db.json', 'database/')
@app.route('/', methods=['GET'])def home_page(): return "Tada! My simple Flask app is running!"
@app.route('/register', methods=['POST'])def register(): name = request.json['name'] username = request.json['username'] password = request.json['password'] if myDatabase.query('users', Query().username == username): return jsonify({"error": "Account already exists"}) myDatabase.insert('users', {'name': name, 'username': username, 'password': password}) return jsonify({'status': 'success'})
@app.route('/login', methods=['POST'])def login(): username = request.json['username'] password = request.json['password'] user = myDatabase.query('users', Query().username == username and Query().password == password) if user: return jsonify({ 'status': 'success', 'token': create_access_token(identity=username) }) return jsonify({'error': 'Account does not exist'})
@jwt_required()@app.route('/index', methods=['GET'])def index(): verify_jwt_in_request() current_user = get_jwt_identity() if current_user: return jsonify({'status': 'success', 'username': current_user}) return jsonify({'error': 'Invalid token'})
app.run(host='localhost', port=5000)Conclusion
In this final article, I’ve introduced more advanced concepts like authentication and token-based authorization using JWTs. I hope it was helpful! If you have any questions or comments, feel free to leave them below — I’ll respond as soon as I can.