📜 ⬆️ ⬇️

We write your URL Shortener

image

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:

image

image

The result of our URL Shortener is:

image

You can try it here .

Source: https://habr.com/ru/post/96710/


All Articles