Create Your Own URL Shortener Using Flask and SQLite
Creating a URL shortener from scratch is a fantastic way to strengthen your Flask and SQLite skills. In this guide, we’ll walk through how to build a fully functional URL shortener in Python, covering database storage, routing logic, and link redirection—all packed neatly into a clean and minimal application.
1. Project Setup and Dependencies
First, let’s set up the project environment. You’ll need Python 3.x and pip
installed. Create a new directory for your project and initialize a virtual environment:
mkdir flask-url-shortener
cd flask-url-shortener
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
Install Flask and Flask-SQLAlchemy:
pip install Flask Flask-SQLAlchemy
Now, create the following file structure:
/flask-url-shortener/
│
├── app.py
├── models.py
├── templates/
│ └── index.html
└── static/
2. Defining the Database Model
Our shortened URLs need to be stored and retrievable. Let’s use SQLite for this, leveraging Flask-SQLAlchemy as an ORM. In models.py
:
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import string
import random
# This will be initialized by app.py
db = SQLAlchemy()
def generate_short_id(num_of_chars):
return ''.join(random.choices(string.ascii_letters + string.digits, k=num_of_chars))
class URL(db.Model):
id = db.Column(db.Integer, primary_key=True)
original_url = db.Column(db.String(512), nullable=False)
short_id = db.Column(db.String(10), unique=True, nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
The generate_short_id()
utility ensures we can generate a random alphanumeric short ID.
3. Building the Core Flask Application
In app.py
, we’ll set up the Flask application, database connection, and define our core routes:
from flask import Flask, request, redirect, render_template, flash
from models import db, URL, generate_short_id
import os
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///urls.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'replace-this-secret'
db.init_app(app)
with app.app_context():
db.create_all()
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
original_url = request.form['original_url']
short_id = generate_short_id(6)
while URL.query.filter_by(short_id=short_id).first():
short_id = generate_short_id(6)
new_link = URL(original_url=original_url, short_id=short_id)
db.session.add(new_link)
db.session.commit()
return render_template('index.html', short_url=request.host_url + short_id)
return render_template('index.html')
@app.route('/')
def redirect_to_url(short_id):
link = URL.query.filter_by(short_id=short_id).first_or_404()
return redirect(link.original_url)
There are two main routes:
/
handles both showing a form and generating short URLs/<short_id>
triggers a lookup by the short code and redirects to the full URL
4. Creating the Frontend with HTML
Let’s make a simple form in templates/index.html
so users can input URLs to shorten:
<!DOCTYPE html>
<html>
<head>
<title>Flask URL Shortener</title>
</head>
<body>
<h1>URL Shortener</h1>
<form method="POST">
<label>Enter URL:</label>
<input type="url" name="original_url" required>
<input type="submit" value="Shorten">
</form>
{% if short_url %}
<p>Shortened URL: <a href="{{ short_url }}">{{ short_url }}</a></p>
{% endif %}
</body>
</html>
This simple UI helps visualize the interaction between users and the back-end without needing a third-party tool like Postman.
5. Tips for Enhancing Performance and Security
Your basic URL shortener is now working—but here are some tips for turning it into a more production-ready service:
- Short Code Collisions: Ensure
generate_short_id
always returns a unique ID. As your user base grows, you may want to increase the code length or apply a retry limit. - Rate Limiting: Prevent abuse by using a Flask extension like
Flask-Limiter
to rate cap form submissions or API access. - Input Validation: Sanitize and validate URLs. For example, check for valid schemes (http/https) using Python’s
urllib.parse
. - Delete Old Links: Add an expiration date field and a cleanup cron job to purge unused links over time.
- Analytics: Enhance your model to track click counts or IP logs for each link.
6. Conclusion
Building your own URL shortener is a meaningful challenge that ties together Flask routing, SQLite storage, and dynamic route handling. You can easily deploy this to Heroku, Vercel, or any VPS to create a personalized utility for link management. Don’t hesitate to customize the model or interface for your own needs—this is just the foundation of what can become an enterprise-worthy microservice!
Useful links: