Skip to main content

Allow Django URLS to be completely rewritten (alias names for system URLs)

Project description

================
django_url_alias
================

About
-----

django_url_alias allows you to completely rewrite certain URLs, if you need to. This is done for incoming URL handling
(URL resolving) and outgoing URLs (via `{% url … %}` or `resolve`). URL rewrites are modular, so you may have static
rewrites (like a dict in settings) and database based rewrites. You may even mix both types by having multiple URL
rewriters.

How it works
------------

django_url_alias provides a special ROOT_URLCONF which intercepts URL resolving on the lowest level. This way it can
rewrite all incoming URLs, so other views will be resolved.

For outgoing URLs (to clarify: "outgoing" does only mean URLs generated by the system, these URLs still may be
internal) The process is a little bit more complex. django_url_alias provides a special `{% url %}` template tag and
its own version of `reverse`. If you use these, everything will just work fine. Sadly there is no sane way to just
replace Django's default behaviour.

Usecase
-------

Although Django's URL handling is really great there may be scanarios it just cannot handle. The flatpage app is one
of the examples URL handling get weird if you need a catchall pattern. As this still works for flatpages you run
into trouble when more then one app needs a similar mechanism (catchall pattern), as only the first one will be handled
correctly (URL matches, further urlconf entries will be ignored).

Other frameworks / CMS / … often use a completely different way to accomplish great URL structure. Instead of having
easy to read system / internal URLs they just put an abstraction layer above all URL handling. This means your
blog entry (for example) may still have an ugly (internal) URL like "blog/entry/15". Now the new URL layer will
take that ugly URL and allow the user or system to define aliases. An alias could for example rewrite "blog/entry/15"
to just "my-trip-to-paris.html". On input URL handling this needs to be reversed, so the requested URL
"my-trip-to-paris.html" will resolve to "blog/entry/15" again.

django_url_alias allows you to just do exactly this. As it does not provide any predefined rules / mechanisms for
rewriting the URL you are free to use whatever rule you want. In theory you could even reuse the good old `SlugField`
and regular expressions. Of course you may use a DB based mapping like so many systems use, too. Below you will find
an example for flatpages, without the need for an catchall pattern.

Usage
-----

Installation
~~~~~~~~~~~~

#. Get django_url_alias into your python `sys.path` (`pip install django_url_alias`)
#. Replace `settings.ROOT_URLCONF` with `"django_url_alias.urls"`
#. Put your old root urlconf into `settings.URL_ALIAS_ROOT_URLCONF`
#. Define your URL rewriting modules using `settings.URL_ALIAS_MODULES`
(see https://github.com/ddanier/django_url_alias/blob/master/example/example/url_aliases.py
and example below)
#. Put `{% load url_alias %}` into your templates, so `{% url %}` gets replaced
#. Use `django_url_alias.resolver.reverse` in your Python code

About URL_ALIAS_MODULES
~~~~~~~~~~~~~~~~~~~~~~~

URL_ALIAS_MODULES is just a list of simple classes to rewrite the URLs Django handles or generates.

.. code:: python

URL_ALIAS_MODULES = (
'path.to.module.aliases.ExampleAliasModule',
)

Each class will be instantiated without any parameters and should provide two methods:

* resolve(self, path): Change incoming URLs
* reverse(self, path): Change outgoing URLs

A simple example may look like this::

class ExampleURLAliasModule(object):
def resolve(self, path):
if path == 'foo/':
return 'bar/'

def reverse(self, path):
if path == 'bar/':
return 'foo/'

Both methods must return nothing (/None) when no rewrite is done. The defined classes will be called in order for
incoming and outgoing URLs. The first module which returns a replacement URL will shortcut further processing, thus
will define the final URL.

Flatpage example
----------------

The flatpages app is in core, so it just gives an nice example. We don't want to use the catchall pattern any more.
For this example to work you will need to go through installation first.

First of all we need to define our internal URL structure. This will not be visible to your visitors, although
the internal URLs are still accessible.

urls.py:: python

urlpatterns = patterns('',
url(r'^flatpage/(?P<pk>[0-9]+)/$', 'example.views.flatpage', name='flatpage'),
)

Then the rewrite needs to be done, so `flatpage.url` will be used to present the external URL structure, while
the internal ID-based URL gets used internally.

URL Rewrite module:: python

from django.contrib.flatpages.models import FlatPage
import re

class FlatpagesURLAliasModule(object):
FLATPAGE_RE = re.compile('^/flatpage/(?P<pk>[0-9]+)/$')

def resolve(self, path):
path = '/' + path # we need a trailing slash for flatpages
try:
flatpage = FlatPage.objects.get(url=path)
return '/flatpage/%d/' % flatpage.pk
except FlatPage.DoesNotExist:
pass # just return nothing

def reverse(self, path):
match = self.FLATPAGE_RE.match(path)
if match:
try:
flatpage = FlatPage.objects.get(pk=match.group('pk'))
return flatpage.url
except FlatPage.DoesNotExist:
pass # just return nothing

*Note:* This is just an example. In an production envirionment you would need to a) check the sites relation and more
importantly b) use some caching. The above code is very inefficient and should NEVER BE USED IN A PRODUCTION
ENVIRIONMENT.


Advantages of implementation
----------------------------

* `request` objects stay clean. You could rewrite URLs using middleware classes which fiddle with `request.path_info`,
but this way you will loose information (or even worse: rewrite information).
* Least obtrusive way of implementation.

Notes
-----

* You should define canonical tags, so internal URLs will not get indexed by search engines.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_url_alias-0.3.0.tar.gz (5.9 kB view details)

Uploaded Source

File details

Details for the file django_url_alias-0.3.0.tar.gz.

File metadata

  • Download URL: django_url_alias-0.3.0.tar.gz
  • Upload date:
  • Size: 5.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.4.1 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/2.7.15

File hashes

Hashes for django_url_alias-0.3.0.tar.gz
Algorithm Hash digest
SHA256 dd047f826501b57ce67b9c2a3177108f5b92f5923c612387cc5a4705d92dd2f2
MD5 310cff6a6be144832ad8215c18b14f4e
BLAKE2b-256 c0f22baf63b5c940b3346f140460078640067ab29bca713c437626aea84110bc

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page