django-url-tracker-fork 0.2.0
A little app that trackes URL changes in a database table to provide HTTP 301 & 410 on request.
License: BSD
Keywords: seo,django,framework

django-url-tracker
==================

.. image:: https://img.shields.io/pypi/v/django-url-tracker-fork.svg?style=flat-square
         :target: https://pypi.python.org/pypi/django-url-tracker-fork

.. image:: https://img.shields.io/travis/saulshanabrook/django-url-tracker.svg?style=flat-square
         :target: https://travis-ci.org/saulshanabrook/django-url-tracker/

.. image:: https://img.shields.io/coveralls/saulshanabrook/django-url-tracker.svg?style=flat-square
         :target: https://coveralls.io/r/saulshanabrook/django-url-tracker

.. image:: https://landscape.io/github/saulshanabrook/django-url-tracker/master/landscape.svg?style=flat-square
   :target: https://landscape.io/github/saulshanabrook/django-url-tracker/master
   :alt: Code Health

The ``django-url-tracker`` is meant to be a easy-to-use addition to
a website to enhance its SEO. This might seem slightly pointless
as `Cool URIs don't change
<http://www.w3.org/Provider/Style/URI.html>`_. I don't want to argue
with that and not changing URL should be the primary goal. In case,
a URL is changed for some reason, however, this can reflect badly in
terms of SEO as search engines do not appreciate ending up on a 404
page when crawling a known URL. To handle these situations nicely
``django-url-tracker`` keeps track of URL changes and when the *old*
URL is called provides a permanent redirect (HTTP 301) or a gone
response (HTTP 410) for deleted URLs.

The tracking is aimed at those URLs that are generated based on
model fields, e.g. a *slug* field. To start tracking URL changes
for a particular model, you simply have to register the model
with ``url_tracker`` and everytime a model is changed or deleted,
URL changes are recorded.

The HTTP repsonses that provide an ``HttpResponsePremanentRedirect``
or ``HttpResponseGone`` are handled similar to the ``flatpages``
middleware, intercepting ``404`` exceptions and checking for the
requested URLs in all existing ``URLChangeRecords``. Depending
on the recorded data the corresponding HTTP response is return or
a ``404`` is raised when no URL matching the requested one can be
found.

Installation
------------

Installation is as easy as::

    pip install django-url-tracker-fork

Done!

Configuration
-------------

To start using ``url_tracker`` in your project. Just add the
following two lines to your ``settings.py``:

1. Add the middleware ``url_tracker.middleware.URLChangePermanentRedirectMiddleware``
   to the end of  ``MIDDLEWARE_CLASSES`` which should look similar
   to this afterwards::

        MIDDLEWARE_CLASSES = (
            'django.middleware.common.CommonMiddleware',
            'django.contrib.sessions.middleware.SessionMiddleware',
            'django.middleware.csrf.CsrfViewMiddleware',
            'django.contrib.auth.middleware.AuthenticationMiddleware',
            'django.contrib.messages.middleware.MessageMiddleware',
            'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
            'url_tracker.middleware.URLChangePermanentRedirectMiddleware',
        )

2. Add ``url_tracker`` and ``django.contrib.contenttypes``, included by
   default, to your ``INSTALLED_APPS``::

        INSTALLED_APPS = (
            "django.contrib.contenttypes",
            "url_tracker",
        )


Now you are able to use ``url_tracker`` within you project. All that
remains to do is registering a model for tracking.

Tracking A Model
----------------

This is just a simple example of how to track a model. Let's assume we
have a model ``Project`` that hold details on this particular project and
is made available at the URL ``http://www.example.com/project/some-project/``.
The project's URL is based on the ``SlugField`` of our model. The model could
look like this::

    class Project(models.Model):
        name = models.CharField(max_length=20)
        slug = models.SlugField(max_length=20)
        description = models.CharField(max_length=500)


I will not go into details of how to create the slug as I think this is
common practise. So for now we just assume that ``slug`` is populated
automatically from ``name``. One other thing, however, is required for
the tracker to work, the ``get_absolute_url`` method. Let's add this to
the model::

    class Project(models.Model):
        ...

        @models.permalink
        def get_absolute_url(self):
            return ('project-detail', (), {'slug': self.slug})

And now the missing link to actually start tracking URL changes. Add the
``URLTrackingMixin`` to your model and add the following command to the
bottom of the class definition (or the file if you prefer that)::

    import url_tracker

    class Project(url_tracker.URLTrackingMixin, models.Model):
        ...

    url_tracker.track_url_changes_for_model(Project)


To change which functions are called to tracks urls, add a
``url_tracking_methods`` attribute to the clast, which is a list of
method names to track. By default the the list contains
``get_absolute_url``.

You are done. If you go to the admin interface, create a new project
and then change its slug (which changes its URL) you will see a new
``URLChangeRecord`` reflecting the change. Opening the ``old_url`` should
then redirect you to the ``new_url``.

Contributing
------------

If you find issues or would like to see a feature suppored, head over to
the `issues section:
<https://github.com/saulshanabrook/django-url-tracker/issues>`_ and report it.

To contribute code in any form, fork the `github repository:
<https://github.com/saulshanabrook/django-url-tracker>`_ and clone it locally.
Create a new branch for your feature::

    git commit -b feature/whatever-you-like

Then make sure all the tests past (and write new ones for any new features)::

    docker-compose run --rm tests

push the finished feature to github and open a pull request form the branch.