Welcome, aspiring web developers! Today, we’re going to embark on a fun and practical journey into the world of web development using Django. We’ll be building a simple URL shortener, a project that’s both useful and a fantastic way to learn core Django concepts. Think of services like Bitly or tinyurl.com – that’s what we’re aiming to create, albeit in a simplified form.
What is a URL Shortener?
Before we dive into the code, let’s clarify what a URL shortener does. Its primary purpose is to take a long, often cumbersome web address (URL) and transform it into a much shorter, more manageable one. When someone clicks on the shortened URL, they are seamlessly redirected to the original long URL. This is incredibly useful for sharing links on social media, in text messages, or anywhere space is limited.
Why Django?
Django is a powerful, high-level Python web framework that encourages rapid development and clean, pragmatic design. It’s built with the philosophy of “Don’t Repeat Yourself” (DRY), meaning it provides many built-in features and tools to help you build robust web applications efficiently. For beginners, Django offers a structured way to learn web development, handling many of the complexities of building web services for you.
Project Setup: Getting Started
First things first, we need to set up our Django project. If you don’t have Python and Django installed, I recommend doing so first. You can find excellent installation guides on the official Python and Django websites.
Once you have them installed, open your terminal or command prompt and let’s create a new Django project:
django-admin startproject url_shortener_project
cd url_shortener_project
This command creates a directory named url_shortener_project with the basic structure of a Django project. The cd url_shortener_project command moves us into that directory.
Now, let’s create a Django app within our project. An app is a self-contained module that performs a specific function. We’ll call our app shortener:
python manage.py startapp shortener
This creates a shortener directory containing files like models.py (for database structure), views.py (for handling requests), and urls.py (for URL routing).
We also need to tell our project about this new app. Open url_shortener_project/settings.py and add 'shortener', to the INSTALLED_APPS list:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'shortener', # Add this line
]
Designing Our Data Model
Every URL shortener needs to store information about the original long URLs and their corresponding short codes. Django’s Object-Relational Mapper (ORM) makes this incredibly easy. We’ll define a model in shortener/models.py:
from django.db import models
class Url(models.Model):
long_url = models.URLField(max_length=1000) # Stores the original, long URL
short_code = models.CharField(max_length=10, unique=True) # Stores the unique short code
def __str__(self):
return f"{self.short_code} -> {self.long_url}"
Explanation of Terms:
models.Model: This is the base class for all Django model classes. It tells Django that this class represents a database table.long_url = models.URLField(max_length=1000): This defines a field namedlong_url.models.URLFieldis a special type of field designed to store URLs.max_length=1000specifies the maximum number of characters this field can hold.short_code = models.CharField(max_length=10, unique=True): This defines a field namedshort_code.models.CharFieldis for storing text strings.max_length=10means the short code will be at most 10 characters long.unique=Trueis crucial – it ensures that no twoUrlobjects can have the sameshort_code, which is essential for our shortener to work without conflicts.def __str__(self): This is a special Python method that defines how an object of this class should be represented as a string. When you see aUrlobject in the Django admin or in a print statement, this is what will be displayed.
Now, we need to create the database table based on this model. First, we create migration files, which are instructions for Django to update the database:
python manage.py makemigrations
Then, we apply these migrations to our database:
python manage.py migrate
If you’re using Django’s default SQLite database, this will create the necessary tables.
Creating Views: The Logic
Our views will handle the core functionality: taking a long URL and creating a short one, and then redirecting from a short URL to its original. Let’s create these in shortener/views.py.
First, we need a way to generate short codes. For simplicity, we’ll use Python’s random module.
import random
import string
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect
from .models import Url
def home(request):
if request.method == 'POST':
long_url = request.POST['long_url']
# Generate a random short code
short_code = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
# Ensure the short code is unique
while Url.objects.filter(short_code=short_code).exists():
short_code = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
# Save the URL and its short code to the database
new_url = Url.objects.create(long_url=long_url, short_code=short_code)
# Construct the shortened URL
short_url = request.build_absolute_uri('/') + short_code
return render(request, 'home.html', {'short_url': short_url})
return render(request, 'home.html')
def redirect_url(request, short_code):
try:
# Find the URL object by its short code
url_entry = Url.objects.get(short_code=short_code)
# Redirect to the original long URL
return HttpResponseRedirect(url_entry.long_url)
except Url.DoesNotExist:
# If the short code is not found, render a 404 page or an error message
return render(request, '404.html', {'error_message': 'Short URL not found'})
Explanation of Terms:
render(request, template_name, context): This is a Django shortcut function. It loads a specified template, fills it with the data provided in thecontextdictionary, and returns anHttpResponseobject.redirect(to): Another shortcut, which redirects the user’s browser to a different URL.request.method == 'POST': When a form is submitted, the request method is usually ‘POST’. This checks if the request was a form submission.request.POST['long_url']: This retrieves the value of the form field namedlong_urlfrom the submitted POST data.random.choices(string.ascii_letters + string.digits, k=6): This generates a list of 6 random characters, chosen from all uppercase letters (string.ascii_letters), lowercase letters (string.ascii_letters), and digits (string.digits).''.join(...): This takes the list of characters generated above and joins them together into a single string.Url.objects.filter(short_code=short_code).exists(): This is how we query our database.Url.objectsis the manager for theUrlmodel.filter()selects objects that match the criteria (in this case, whereshort_codeis equal to our generatedshort_code)..exists()returnsTrueif any matching objects are found,Falseotherwise. This is our check for uniqueness.Url.objects.create(long_url=long_url, short_code=short_code): This creates a newUrlrecord in the database with the providedlong_urlandshort_code.request.build_absolute_uri('/'): This creates the full URL for the current site, including the scheme (http/https) and domain. Appending theshort_codegives us the complete shortened URL.HttpResponseRedirect(url_entry.long_url): This explicitly creates an HTTP redirect response, telling the browser to go to thelong_url.Url.objects.get(short_code=short_code): This attempts to retrieve a singleUrlobject where theshort_codematches. If no such object exists, it raises aUrl.DoesNotExistexception.try...except Url.DoesNotExist:: This is standard Python error handling. If theUrl.DoesNotExistexception occurs (meaning the short code wasn’t found), the code inside theexceptblock is executed.
Designing the User Interface (HTML Templates)
We need a simple HTML page for users to input their long URLs and see their generated short URLs. Create a templates directory inside your shortener app. Then, inside templates, create a home.html file. Also, create a 404.html file for when a short URL is not found.
shortener/templates/home.html:
<!DOCTYPE html>
<html>
<head>
<title>URL Shortener</title>
</head>
<body>
<h1>URL Shortener</h1>
<form method="post">
{% csrf_token %}
<label for="long_url">Enter long URL:</label><br>
<input type="url" id="long_url" name="long_url" required size="50"><br><br>
<button type="submit">Shorten</button>
</form>
{% if short_url %}
<p>Your shortened URL is: <a href="{{ short_url }}">{{ short_url }}</a></p>
{% endif %}
</body>
</html>
shortener/templates/404.html:
<!DOCTYPE html>
<html>
<head>
<title>Not Found</title>
</head>
<body>
<h1>Oops!</h1>
<p>{{ error_message }}</p>
<p><a href="/">Go back to the homepage</a></p>
</body>
</html>
Explanation of Terms:
{% csrf_token %}: This is a Django template tag that is essential for security. It generates a hidden input field that helps protect your website from Cross-Site Request Forgery (CSRF) attacks.method="post": This attribute in the<form>tag tells the browser to send the form data using the HTTP POST method.name="long_url": This is important because it’s how we’ll access the input’s value in our Django view (request.POST['long_url']).required: This HTML5 attribute makes the input field mandatory. The browser will prevent form submission if this field is empty.{% if short_url %}…{% endif %}: This is a Django template tag that checks if a variable namedshort_urlexists and has a value. If it does, the content within theifblock is displayed.{{ short_url }}: This is how you display the value of a variable in a Django template.
Mapping URLs to Views
We need to tell Django which URL should trigger which view. We do this by creating urls.py files.
First, in your project directory (url_shortener_project), create a urls.py file if one doesn’t exist (Django usually generates one). Then, include your shortener app’s URLs:
url_shortener_project/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('shortener.urls')), # Include our app's URLs
]
Now, create a urls.py file inside your shortener app directory:
shortener/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'), # Maps the root URL to the home view
path('<str:short_code>/', views.redirect_url, name='redirect_url'), # Maps short codes to the redirect_url view
]
Explanation of Terms:
path('route', view_function, name='url_name'): This is the core of Django’s URL routing.'route': This is the URL pattern. For example,''matches the root of the site, and'<str:short_code>/'matches any string followed by a slash, capturing that string into a variable namedshort_code.view_function: This is the Python function (from yourviews.py) that will be called when this route is matched.name='url_name': This is an optional but highly recommended argument. It gives a unique name to this URL pattern, making it easier to reference in your code and templates.
include('app_name.urls'): This tells Django to look for URL patterns defined in the specified app’surls.pyfile.
Testing Our URL Shortener
It’s time for the moment of truth! Save all your files, and run the Django development server:
python manage.py runserver
Open your web browser and go to http://127.0.0.1:8000/. You should see a simple form. Enter a long URL (e.g., https://www.djangoproject.com/), and click “Shorten.” You should then see your newly generated short URL.
Now, copy that short URL and paste it into your browser’s address bar. You should be automatically redirected to the original long URL!
If you try to access a non-existent short URL (e.g., http://127.0.0.1:8000/nonexistentcode/), you should see the “Oops! Short URL not found” message from our 404.html template.
Next Steps and Enhancements
This is a basic implementation, but you can expand it in many ways:
- Custom Short Codes: Allow users to choose their own short codes.
- Analytics: Track how many times each short URL is clicked.
- User Accounts: Allow users to manage their shortened URLs.
- Error Handling: Add more robust error handling and user feedback.
- Styling: Make the website look nicer with CSS.
- Deployment: Learn how to deploy your Django application to a live server.
Conclusion
Congratulations! You’ve successfully built a functional URL shortener using Django. This project has introduced you to fundamental Django concepts like models, views, templates, and URL routing. Keep experimenting and building – the world of web development is vast and exciting!
Leave a Reply
You must be logged in to post a comment.