Create Your Own URL Shortener Using Flask and SQLite

Create Your Own URL Shortener Using Flask and SQLite

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: