How to generate temporary URLs in Django

If you don't expect to get a large response rate, then you should try to store all of the data in the URL itself. This way, you don't need to store anything in the database, and will have data storage proportional to the responses rather than the emails sent.

Updated: Let's say you had two strings that were unique for each user. You can pack them and unpack them with a protecting hash like this:

import hashlib, zlib
import cPickle as pickle
import urllib

my_secret = "michnorts"

def encode_data(data):
    """Turn `data` into a hash and an encoded string, suitable for use with `decode_data`."""
    text = zlib.compress(pickle.dumps(data, 0)).encode('base64').replace('\n', '')
    m = hashlib.md5(my_secret + text).hexdigest()[:12]
    return m, text

def decode_data(hash, enc):
    """The inverse of `encode_data`."""
    text = urllib.unquote(enc)
    m = hashlib.md5(my_secret + text).hexdigest()[:12]
    if m != hash:
        raise Exception("Bad hash!")
    data = pickle.loads(zlib.decompress(text.decode('base64')))
    return data

hash, enc = encode_data(['Hello', 'Goodbye'])
print hash, enc
print decode_data(hash, enc)

This produces:

849e77ae1b3c eJzTyCkw5ApW90jNyclX5yow4koMVnfPz09JqkwFco25EvUAqXwJnA==
['Hello', 'Goodbye']

In your email, include a URL that has both the hash and enc values (properly url-quoted). In your view function, use those two values with decode_data to retrieve the original data.

The zlib.compress may not be that helpful, depending on your data, you can experiment to see what works best for you.


models

class TempUrl(models.Model):
    url_hash = models.CharField("Url", blank=False, max_length=32, unique=True)
    expires = models.DateTimeField("Expires")

views

def generate_url(request):
    # do actions that result creating the object and mailing it

def load_url(request, hash):
    url = get_object_or_404(TempUrl, url_hash=hash, expires__gte=datetime.now())
    data = get_some_data_or_whatever()
    return render_to_response('some_template.html', {'data':data}, 
                              context_instance=RequestContext(request))

urls

urlpatterns = patterns('', url(r'^temp/(?P<hash>\w+)/$', 'your.views.load_url', name="url"),)

//of course you need some imports and templates


You could set this up with URLs like:

http://yoursite.com/temp/1a5h21j32

Your URLconf would look something like this:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^temp/(?P<hash>\w+)/$', 'yoursite.views.tempurl'),
)

...where tempurl is a view handler that fetches the appropriate page based on the hash. Or, sends a 404 if the page is expired.

Tags:

Url

Django