
URL shortener is one that reduces a long URL into something considerably shorter. It’s very useful in case you would like to pass a link through social networks or by SMS in such a manner that the link doesn’t look cluttered. We are, in this post, going to walk you through building a basic URL shortener using Python.
Prerequisites
Before we begin, ensure you have the following:
- Basic knowledge of Python.
- Familiarity with web frameworks like Flask.
- A working installation of Python and pip.
- Basic understanding of web development concepts.
- A text editor like VSCode or Sublime.
Install Python and Flask
If you don’t have Python installed, download and install the latest version from the official website. Then, install Flask:
pip install Flask
Project Setup
Create Project Folder:
Create a new folder for your project.
mkdir url_shortener
cd url_shortener
Create Virtual Environment (optional but recommended):
python -m venv venv
source venv/bin/activate # On Windows, use `venv\Scripts\activate`
Create a Basic File Structure:
Structure the project as follows:
url_shortener/
├── app.py
├── models.py
├── controllers/
│ ├── redirects_controller.py
│ └── api_controller.py
├── templates/
│ └── index.html
└── static/
└── style.css
Database Design
We’ll use SQLite for simplicity, but this project can be extended to work with other databases like PostgreSQL or MySQL.
Create a Database: The database will have a table to store the original and shortened URLs.
CREATE TABLE links (
id INTEGER PRIMARY KEY AUTOINCREMENT,
original_url TEXT NOT NULL,
short_url TEXT NOT NULL UNIQUE
);
Add Sample Data: You can populate it with some test data to check the application.
The Link Model
In models.py, we’ll define the structure for the URL and provide functions to interact with the database.
import sqlite3
import random
import string
DATABASE = 'url_shortener.db'
def get_db():
db = sqlite3.connect(DATABASE)
db.row_factory = sqlite3.Row
return db
def generate_short_url():
return ''.join(random.choices(string.ascii_letters + string.digits, k=6))
class Link:
@staticmethod
def create(original_url):
short_url = generate_short_url()
db = get_db()
db.execute("INSERT INTO links (original_url, short_url) VALUES (?, ?)",
(original_url, short_url))
db.commit()
return short_url
@staticmethod
def get_original_url(short_url):
db = get_db()
row = db.execute("SELECT original_url FROM links WHERE short_url = ?", (short_url,)).fetchone()
if row:
return row['original_url']
return None
Setting Up Dependencies
Make sure to import the necessary dependencies in your main application file, app.py.
from flask import Flask, redirect, render_template, request, jsonify
from models import Link
Creating Controllers
Redirects Controller
In controllers/redirects_controller.py, create a controller that handles the redirection to the original URL.
from flask import redirect
from models import Link
def redirect_to_url(short_url):
original_url = Link.get_original_url(short_url)
if original_url:
return redirect(original_url)
return "URL not found", 404
API Controller
In controllers/api_controller.py, we’ll create an API endpoint to generate short URLs.
from flask import jsonify, request
from models import Link
def create_short_url():
original_url = request.json.get('original_url')
if original_url:
short_url = Link.create(original_url)
return jsonify({"short_url": short_url}), 201
return jsonify({"error": "Invalid URL"}), 400
Setting Up Routes
In app.py, set up the routes for redirecting, creating, and displaying the basic interface.
from flask import Flask, render_template, request
from controllers.redirects_controller import redirect_to_url
from controllers.api_controller import create_short_url
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/<short_url>')
def redirect_to_short_url(short_url):
return redirect_to_url(short_url)
@app.route('/api/create', methods=['POST'])
def api_create():
return create_short_url()
if __name__ == '__main__':
app.run(debug=True)
Application Controller
In app.py, ensure all the routes are registered and controllers are correctly wired. We already did this with the index, redirect_to_short_url, and api_create routes.
Basic Web Interface
In templates/index.html, create a basic form where users can input a URL and get a shortened version.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>URL Shortener</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<div class="container">
<h1>URL Shortener</h1>
<form action="/" method="POST">
<input type="url" name="url" placeholder="Enter URL" required>
<button type="submit">Shorten</button>
</form>
{% if shortened_url %}
<p>Shortened URL: <a href="{{ shortened_url }}" target="_blank">{{ shortened_url }}</a></p>
{% endif %}
</div>
</body>
</html>
In app.py, add a route to handle form submissions and generate a short URL.
@app.route('/', methods=['POST'])
def shorten_url():
original_url = request.form['url']
short_url = Link.create(original_url)
shortened_url = request.host_url + short_url
return render_template('index.html', shortened_url=shortened_url)
Adding Error Pages
It’s important to handle errors like invalid URLs or broken links gracefully. Flask allows you to easily add custom error pages.
In app.py, add error handling for 404 errors.
@app.errorhandler(404)
def page_not_found(error):
return render_template('404.html'), 404
Create a 404.html page in the templates/ folder:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 - Not Found</title>
</head>
<body>
<h1>Oops! The URL you are looking for is not found.</h1>
</body>
</html>
Conclusion
You’ve now developed a simple but functional URL shortener using Python and Flask. The project included defining routes, controllers, and a web interface. From this foundation, you can add more advanced features like user authentication, analytics, and custom short URL schemes.