
This article describes how to create a simple link 
shortening , such as 
bit.ly or 
goo.gl.')
So, go to the directory with your project and create the application. Let it be named 
'shortener' .
$ django-project startapp shortener
To begin, let us describe a simple 
URL configuration that will determine what the user needs according to his request.
<br/> # urls.py <br/> from django.conf.urls.defaults import * <br/> <br/> urlpatterns = patterns ( '' , <br/> (r '^ $' , 'views .index ' ), <br/> (r ' ^ (? P <key>. {3}) $ ' , ' views.redirect ' ), <br/>) <br/>
We will consider the case when using the address example.com to shorten it, that is, the configuration presented above is the only one (do not forget to specify ROOT_URLCONF in settings.py). If you use an address like example.com/shortener/, do not forget to connect your configuration to the main one using the include mechanism .
Now, when accessing 
example.com , the view function will call the 
index from the 
views.py file, the rest of the addresses, the length of which is 3 three characters (no domain), we will try to “expand” using the 
redirect function from the same file. To shorten the links, we will use Latin letters in different case and numbers. The length of the "key" will be three characters, this is quite enough for not very mass services (62 ^ 3 options).
Our next step is to define the model, that is, the description of the data at the database level.
# models.py <br/> from django.db import models<br/> <br/> from datetime import datetime<br/> from random import choice<br/> import string<br/> <br/> <br/> def generate_key ():<br/> chars = string .digits + string .letters<br/> return '' .join(choice(chars) for _ in range ( 3 ))<br/> <br/> class ShortUrl (models.Model):<br/> <br/> key = models.CharField(max_length= 3 , primary_key=True, default= generate_key )<br/> target = models.URLField(verify_exists=False, unique=True)<br/> added = models.DateTimeField(auto_now_add=True, editable=False)<br/> <br/> def __unicode__ (self):<br/> return '%s %s' % ( self .target, self .key)<br/> <br/> <br/> class Hit (models.Model):<br/> <br/> target = models.ForeignKey( ShortUrl )<br/> time = models.DateTimeField(auto_now_add=True, editable=False)<br/> referer = models.URLField(blank=True, verify_exists=False)<br/> ip = models.IPAddressField(blank=True)<br/> user_agent = models.CharField(blank=True, max_length= 100 ) <br/>
After importing the necessary functions and models, we will implement a function that will generate a random key from the specified characters. The following describes the 
ShortUrl class, which is responsible for presenting our short link in the database. Each object of this class has a unique 
key attribute, a field in which the “long” link is stored, as well as the date the link was created. Then comes the 
Hit class. With it, we will store information about a click on a shortened link, namely, the time of the click, the 
IP clicked, its 
User Agent and 
Referer , and the “long” link.
Pay attention to the arguments of the fields, later they will be very important.
Our page on which the user can shorten his link will be very minimalistic - one form and one button (it is shown in the first picture). Let's describe this small form, its code will be contained in 
forms.py .
#forms.py <br/> from django import forms<br/> <br/> class UrlForm (forms.Form): <br/> url = forms.URLField(label= 'url' , verify_exists=False) <br/>
Everything is very simple here - one field with which we will process the long link sent by the user.
It's time to write a view that will process the data passed by our 
URL configuration. First we describe the function 
make_short_url and import the necessary modules and functions.
#views.py <br/> from django.http import HttpResponseRedirect<br/> from django.shortcuts import render_to_response, get_object_or_404<br/> from django.template import RequestContext<br/> <br/> from forms import UrlForm<br/> from models import ShortUrl, Hit<br/> <br/> <br/> def make_short_url (url):<br/> short_url = ShortUrl.objects.get_or_create(target=url)[ 0 ]<br/> short_url.save()<br/> return 'http://example.com/%s' % (short_url.key)<br/>
After importing, a function is implemented that takes a certain reference, creates a corresponding object of class 
ShortUrl and returns an already shortened reference (it was generated during the creation of the object). It is also possible to use 
Site.objects.get_current (). Domain from 
django.contrib.sites.models .
Now we need to write functions that process the form and implement the unfolding of the “short” link, that is, the redirect.
#views.py (continuation) <br/> def index (request):<br/> if request.method == 'POST' :<br/> form = UrlForm(request.POST)<br/> if form.is_valid():<br/> url = form.cleaned_data.get( 'url' )<br/> url = make_short_url(url)<br/> return render_to_response( 'shortener.html' , { 'url' :url})<br/> else :<br/> form = UrlForm(label_suffix= '' )<br/> return render_to_response( 'shortener.html' , { 'form' : form, 'url' : '' })<br/> <br/> <br/> def redirect (request, key):<br/> target = get_object_or_404(ShortUrl, key=key)<br/> <br/> try :<br/> hit = Hit()<br/> hit.target = target<br/> hit.referer = request.META.get( "HTTP_REFERER" , "" )<br/> hit.ip = request.META.get( "REMOTE_ADDR" , "" )<br/> hit.user_agent = request.META.get( "HTTP_USER_AGENT" , "" )<br/> hit.save()<br/> except IntegrityError:<br/> pass <br/> <br/> return HttpResponseRedirect(target.target) <br/>
The 
index function displays an empty form if the user has not yet accessed it, and processes it in the case of a 
POST request. In the first case, the template 
shortener.html , which is responsible for the interface, is passed the form itself and a blank link, in the second - only a shortened link. This is followed by the 
redirect function, which is referenced by the 
URL configuration, if it found the user's request for a request to deploy a “short” link. Before a simple redirect, we create an object of the 
Hit class, described in 
models.py , with the corresponding attributes obtained from the 
request object. I also advise you to read the comments, there are a lot of interesting things about the “except: pass” construction.
Just a little bit left, a little more and we will have our own link shortening!
It is time to describe our template 
shortener.html , responsible for the 
HTML presentation of the form and a shortened link. Remember what parameters it takes.
<!--shortener.html--> <br/>{% if not url %}<br/> < form action ="." method ="post" > <br/> {{ form.as_p }}<br/> < input type ="submit" name ="submit" value ="submit"/> <br/> </ form > <br/>{% else %}<br/> < a href ="{{url}}"></ a > {{ url }} </ a > <br/>{% endif %} <br/>
Basically, you can already use this code - the URL Shortener itself has already been created. It remains to describe the presentation of our data in the administrator interface (do not forget to include the appropriate configuration in the 
urls.py file).
#admin.py <br/> from django.contrib import admin<br/> <br/> from models import ShortUrl, Hit<br/> <br/> <br/> class ShortUrlAdmin (admin.ModelAdmin):<br/> fields = ( 'target' , 'key' )<br/> list_display = ( 'key' , 'target' , 'added' )<br/> ordering = ( '-added' ,)<br/> list_filter = ( 'added' ,)<br/> date_hierarchy = 'added' <br/> <br/>admin. site .register(ShortUrl, ShortUrlAdmin )<br/> <br/> <br/> class HitAdmin (admin.ModelAdmin):<br/> list_display = ( 'target' , 'ip' , 'user_agent' , 'referer' , 'time' )<br/> ordering = ( '-time' ,)<br/> list_filter = ( 'target' , 'referer' , 'time' )<br/> date_hierarchy = 'time' <br/> <br/>admin. site .register(Hit, HitAdmin ) <br/>
That's all. It remains to perform
$ python manage.py syncdb
And enjoy the result :)
Admin Interface:


The result of our URL Shortener is:

You can try it 
here .