Writing Your Shortener URL
The article describes how to create a simple sokraschalki links, like bit.ly or goo.gl .
So, we go into the directory with your project and create the application. Let it be called 'shortener' .
$ django-project startapp shortener
First, let’s describe a simple URL configuration that will determine what the user needs in accordance with his request.
django.conf.urls.defaults import *
# urls.py
from
urlpatterns = patterns ('',
(r '^ $', 'views.index'),
(r '^ (? P. {3}) $ ',' views.redirect '),
)
We will consider the case when the address example.com is used for reduction, that is, the above configuration 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, it will call the index submission function from the views.py file , the rest of the addresses, the length of which is 3 three characters (without a domain), we will try to “expand” using the redirect functionfrom the same file. To shorten the links, we will use Latin letters in different cases 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 will be to determine the model, that is, a description of the data at the database level.
# models.py
from django.db import models
from datetime import datetime
from random import choice
import string
def generate_key():
chars = string.digits + string.letters
return ''.join(choice(chars) for _ in range(3))
class ShortUrl(models.Model):
key = models.CharField(max_length=3, primary_key=True, default=generate_key)
target = models.URLField(verify_exists=False, unique=True)
added = models.DateTimeField(auto_now_add=True, editable=False)
def __unicode__(self):
return '%s %s' % (self.target, self.key)
class Hit(models.Model):
target = models.ForeignKey(ShortUrl)
time = models.DateTimeField(auto_now_add=True, editable=False)
referer = models.URLField(blank=True, verify_exists=False)
ip = models.IPAddressField(blank=True)
user_agent = models.CharField(blank=True, max_length=100)
After importing the necessary functions and models, we implement a function that will generate a random key from the given characters. The following describes the ShortUrl class , which is responsible for representing our shortened 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 class Hit . Using it, we will store information about the click on the shortened link, namely the time of the click, the IP of the clicker, his User Agent and Referer , and of 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
from django import forms
class UrlForm(forms.Form):
url = forms.URLField(label='url', verify_exists=False)
Everything is very simple here - one field, with the help of 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 make_short_url function and import the necessary modules and functions.
#views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from forms import UrlForm
from models import ShortUrl, Hit
def make_short_url(url):
short_url = ShortUrl.objects.get_or_create(target=url)[0]
short_url.save()
return 'http://example.com/%s' % (short_url.key)
After imports, a function is implemented that takes a certain link, creates a corresponding object of the ShortUrl class and returns an already shortened link (it was generated during the creation of the object). You can also use Site.objects.get_current (). Domain from django.contrib.sites.models .
Now we need to write functions that process the form and implement the deployment of a “short” link, that is, a redirect.
#views.py (continuation)
def index(request):
if request.method == 'POST':
form = UrlForm(request.POST)
if form.is_valid():
url = form.cleaned_data.get('url')
url = make_short_url(url)
return render_to_response('shortener.html', {'url':url})
else:
form = UrlForm(label_suffix='')
return render_to_response('shortener.html', {'form': form, 'url': ''})
def redirect(request, key):
target = get_object_or_404(ShortUrl, key=key)
try:
hit = Hit()
hit.target = target
hit.referer = request.META.get("HTTP_REFERER", "")
hit.ip = request.META.get("REMOTE_ADDR", "")
hit.user_agent = request.META.get("HTTP_USER_AGENT", "")
hit.save()
except IntegrityError:
pass
return HttpResponseRedirect(target.target)
The index function displays an empty form if the user has not yet accessed it, and processes it in case of a POST request. In the first case , the form shortener.html , which is responsible for the interface, is passed the form itself and an empty link, in the second - only a shortened link. This is followed by the redirect function , which is referred to by the URL configuration if it considers 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, they have a lot of interesting things about the “except: pass” construction.
It remains just a little bit, a little more and we will have our own shortener links!
The time has come to describe our shortener.html template , which is responsible for the HTML representation of the form and the shortened link. Remember what parameters it takes.
{% if not url %}
{% else %}
{{ url }}
{% endif %}
Basically, you can already use this code - the Shortener URL itself has already been created. It remains to describe the presentation of our data in the admin interface (do not forget to connect the appropriate configuration in the urls.py file ).
#admin.py
from django.contrib import admin
from models import ShortUrl, Hit
class ShortUrlAdmin(admin.ModelAdmin):
fields = ('target', 'key')
list_display = ('key', 'target', 'added')
ordering = ('-added',)
list_filter = ('added',)
date_hierarchy = 'added'
admin.site.register(ShortUrl, ShortUrlAdmin)
class HitAdmin(admin.ModelAdmin):
list_display = ('target', 'ip', 'user_agent', 'referer', 'time')
ordering = ('-time',)
list_filter = ('target', 'referer', 'time')
date_hierarchy = 'time'
admin.site.register(Hit, HitAdmin)
That's all. Left to execute
$ python manage.py syncdb
And enjoy the result :)
Admin interface:
The result of our URL Shortener'a:
You can try it here .