URL Shortener using Flask — with Source Code
--
Hello guys, in today’s blog we will build a URL Shortener using Flask. This will be an exciting blog, so without any further due, let’s do it…
Read the full blog here — https://machinelearningprojects.net/url-shortener-using-flask/
Checkout the video here…
Sneak Peek at our URL Shortener using Flask
Install required libraries
pip install flask hashids
Code Files For our URL Shortener
Our Project majorly consists of the following 3 code files:
- app.py
- index.html
- stats.html
app.py
# URL Shortener using Flask
import sqlite3
from hashids import Hashids
from flask import Flask, render_template, request, flash, redirect, url_for
app = Flask(__name__)
app.config['SECRET_KEY'] = 'this should be a secret random string'
connection = sqlite3.connect('database.db')
c = connection.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS urls(
id INTEGER PRIMARY KEY AUTOINCREMENT,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
original_url TEXT NOT NULL,
clicks INTEGER NOT NULL DEFAULT 0
)''')
def get_db_connection():
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row
return conn
hashids = Hashids(min_length=4, salt=app.config['SECRET_KEY'])
@app.route('/', methods=('GET', 'POST'))
def index():
conn = get_db_connection()
if request.method == 'POST':
url = request.form['url']
if not url:
flash('The URL is required!')
return redirect(url_for('index'))
url_data = conn.execute('INSERT INTO urls (original_url) VALUES (?)',(url,))
conn.commit()
conn.close()
url_id = url_data.lastrowid
hashid = hashids.encode(url_id)
short_url = request.host_url + hashid
return render_template('index.html', short_url=short_url)
return render_template('index.html')
@app.route('/<id>')
def url_redirect(id):
conn = get_db_connection()
original_id = hashids.decode(id)
if original_id:
original_id = original_id[0]
url_data = conn.execute('SELECT original_url, clicks FROM urls WHERE id = (?)', (original_id,)).fetchone()
original_url = url_data['original_url']
clicks = url_data['clicks']
conn.execute('UPDATE urls SET clicks = ? WHERE id = ?',(clicks+1, original_id))
conn.commit()
conn.close()
return redirect(original_url)
else:
flash('Invalid URL')
return redirect(url_for('index'))
@app.route('/stats')
def stats():
conn = get_db_connection()
db_urls = conn.execute('SELECT id, created, original_url, clicks FROM urls').fetchall()
conn.close()
urls = []
for url in db_urls:
url = dict(url)
url['short_url'] = request.host_url + hashids.encode(url['id'])
urls.append(url)
return render_template('stats.html', urls=urls)
index.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Welcome to FlaskShortener</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light">
<a class="navbar-brand" href="{{ url_for('index')}}">FlaskTodo</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="{{ url_for('stats')}}">Stats</a>
</li>
</ul>
</div>
</nav>
<div class="container">
{% for message in get_flashed_messages() %}
<div class="alert alert-danger">{{ message }}</div>
{% endfor %}
<h1>Welcome to FlaskShortener</h1>
<form method="post">
<div class="form-group">
<label for="url">URL</label>
<input type="text" name="url" placeholder="URL to shorten" class="form-control"
value="{{ request.form['url'] }}" autofocus></input>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
{% if short_url %}
<hr>
<span>{{ short_url }}</span><br>
{% endif %}
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
stats.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Welcome to FlaskShortener</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light">
<a class="navbar-brand" href="{{ url_for('index')}}">FlaskTodo</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="{{ url_for('stats')}}">Stats</a>
</li>
</ul>
</div>
</nav>
<h1>{% block title %} FlaskShortener Statistics {% endblock %}</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Short</th>
<th scope="col">Original</th>
<th scope="col">Clicks</th>
<th scope="col">Creation Date</th>
</tr>
</thead>
<tbody>
{% for url in urls %}
<tr>
<th scope="row">{{ url['id'] }}</th>
<td>{{ url['short_url'] }}</td>
<td>{{ url['original_url'] }}</td>
<td>{{ url['clicks'] }}</td>
<td>{{ url['created'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
Our Final Output
Refer to this article for deploying it online — How to Deploy a Flask app online using Pythonanywhere
And this is how you can create a URL Shortener using Flask…
So this is all for this blog folks. Thanks for reading it and I hope you are taking something with you after reading this and till the next time …
Read my last blog — Create an API in Flask and deploy it online
Check out my other machine learning projects, deep learning projects, computer vision projects, NLP projects, and Flask projects at machinelearningprojects.net.