
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.