| 1 | =====================
|
|---|
| 2 | The sitemap framework
|
|---|
| 3 | =====================
|
|---|
| 4 |
|
|---|
| 5 | Django comes with a high-level sitemap-generating framework that makes
|
|---|
| 6 | creating `Google Sitemap`_ XML files easy.
|
|---|
| 7 |
|
|---|
| 8 | .. _Google Sitemap: http://www.google.com/webmasters/sitemaps/docs/en/protocol.html
|
|---|
| 9 |
|
|---|
| 10 | The "sitemap" framework
|
|---|
| 11 | =======================
|
|---|
| 12 |
|
|---|
| 13 | Overview
|
|---|
| 14 | --------
|
|---|
| 15 |
|
|---|
| 16 | The sitemap-generating framework is based largely off of Django's
|
|---|
| 17 | `syndication framework`_. You tell the framework what you want to include
|
|---|
| 18 | in your sitemap by creating ``Sitemap`` classes and pointing to them
|
|---|
| 19 | in your URLconf_.
|
|---|
| 20 |
|
|---|
| 21 | .. _syndication framework: http://www.djangoproject.com/documentation/syndication/
|
|---|
| 22 | .. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
|
|---|
| 23 |
|
|---|
| 24 | Initialization
|
|---|
| 25 | --------------
|
|---|
| 26 |
|
|---|
| 27 | To activate sitemap generation on your Django site, add this line to your
|
|---|
| 28 | URLconf_:
|
|---|
| 29 |
|
|---|
| 30 | ( r'^sitemap.xml$', 'django.contrib.sitemap.views.sitemap', {'sitemaps': sitemaps} )
|
|---|
| 31 |
|
|---|
| 32 | This will tell Django to build a sitemap when a client accesses ``/sitemap.xml``.
|
|---|
| 33 | The name of the sitemap is not important, but the location is. Google will only
|
|---|
| 34 | index links in your sitemap for the current URL level and below. For instance, if
|
|---|
| 35 | ``sitemap.xml`` lives in your root directory, it may reference any URL in your
|
|---|
| 36 | site. However, if your sitemap lives at ``/content/sitemap.xml``, it may only
|
|---|
| 37 | reference URLs under ``/content/``.
|
|---|
| 38 |
|
|---|
| 39 | The sitemap view takes an extra argument: ``{'sitemaps': sitemaps}``. ``sitemaps``
|
|---|
| 40 | should be a dictionary that maps a short section label (i.e. ``blog`` or ``news``)
|
|---|
| 41 | to its ``Sitemap`` class (i.e. ``BlogSitemap`` or ``NewsSitemap``). It may also map
|
|---|
| 42 | to an instance of a ``Sitemap`` class (i.e. ``BlogSitemap(some_var)``).
|
|---|
| 43 |
|
|---|
| 44 | .. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
|
|---|
| 45 |
|
|---|
| 46 | Sitemap Classes
|
|---|
| 47 | ---------------
|
|---|
| 48 |
|
|---|
| 49 | A ``Sitemap`` class is a simple python class that represents a "section" of
|
|---|
| 50 | entries in your sitemap. In the simplest case, all these sections get lumped
|
|---|
| 51 | together in one ``sitemap.xml``. It is also possible to use the framework to
|
|---|
| 52 | generate a sitemap index that references individual sitemap files, one per
|
|---|
| 53 | section.
|
|---|
| 54 |
|
|---|
| 55 | ``Sitemap`` classes must subclass ``django.contrib.sitemap.Sitemap``. They can
|
|---|
| 56 | live anywhere in your codebase.
|
|---|
| 57 |
|
|---|
| 58 | A simple example
|
|---|
| 59 | ----------------
|
|---|
| 60 |
|
|---|
| 61 | Let's assume you have an ``Entry`` model in your blog, and you want to include
|
|---|
| 62 | all the individual links to your blog entries in your sitemap::
|
|---|
| 63 |
|
|---|
| 64 | from django.contrib.sitemap import Sitemap
|
|---|
| 65 | from myproject.blog.models import Entry
|
|---|
| 66 |
|
|---|
| 67 | class BlogSitemap(Sitemap):
|
|---|
| 68 | changefreq = "never"
|
|---|
| 69 | priority = 0.5
|
|---|
| 70 |
|
|---|
| 71 | def items(self):
|
|---|
| 72 | return Entry.objects.filter(is_draft=False)
|
|---|
| 73 |
|
|---|
| 74 | def lastmod(self, obj):
|
|---|
| 75 | return obj.pub_date
|
|---|
| 76 |
|
|---|
| 77 | Note:
|
|---|
| 78 |
|
|---|
| 79 | * ``changefreq`` and ``priority`` are class attributes corresponding to
|
|---|
| 80 | ``<changefreq>`` and ``<priority>`` elements, respectively. They could be
|
|---|
| 81 | made callable as functions, as ``lastmod`` was in the example.
|
|---|
| 82 | * ``items()`` is simply a method that returns a list of objects. The objects
|
|---|
| 83 | returned will get passed to any callable methods corresponding to a sitemap
|
|---|
| 84 | property (``location``, ``lastmod``, ``changefreq``, and ``priority``).
|
|---|
| 85 | * ``lastmod`` should return a ``datetime`` object.
|
|---|
| 86 | * There is no ``location`` method. ``Sitemap`` provides a default implementation
|
|---|
| 87 | for you that calls ``get_absolute_url()`` on each object and returns the result.
|
|---|
| 88 |
|
|---|
| 89 | Shortcuts
|
|---|
| 90 | ---------
|
|---|
| 91 |
|
|---|
| 92 | The sitemap framework provides a couple convenience classes for common cases:
|
|---|
| 93 |
|
|---|
| 94 | * FlatpageSitemap
|
|---|
| 95 | * GenericSitemap
|
|---|
| 96 |
|
|---|
| 97 | The ``FlatpageSitemap`` class looks at all flatpages_ defined for the current ``SITE_ID``
|
|---|
| 98 | (see the sites_ documentation) and creates an entry in the sitemap. These entries include
|
|---|
| 99 | only the ``location`` attribute.
|
|---|
| 100 |
|
|---|
| 101 | The ``GenericSitemap`` class works with any `generic views`_ you already have. To use
|
|---|
| 102 | it, create an instance, passing in the same ``info_dict`` you pass to the
|
|---|
| 103 | generic views. The only requirement is that the dict have a ``queryset`` entry.
|
|---|
| 104 | It may also have a ``date_field`` entry that specifies a date field for objects
|
|---|
| 105 | retrieved from the ``queryset``. This will be used for the ``lastmod`` attribute in
|
|---|
| 106 | the generated sitemap.
|
|---|
| 107 |
|
|---|
| 108 | Here's an example of a URLconf_ using both::
|
|---|
| 109 |
|
|---|
| 110 | from django.conf.urls.defaults import *
|
|---|
| 111 | from django.contrib.sitemap import FlatpageSitemap, GenericSitemap
|
|---|
| 112 | from myproject.blog.models import Entry
|
|---|
| 113 |
|
|---|
| 114 | info_dict = {
|
|---|
| 115 | 'queryset': Entry.objects.all(),
|
|---|
| 116 | 'date_field': 'pub_date',
|
|---|
| 117 | }
|
|---|
| 118 |
|
|---|
| 119 | sitemaps = {
|
|---|
| 120 | 'flatpages': FlatpageSitemap,
|
|---|
| 121 | 'blog': GenericSitemap(info_dict),
|
|---|
| 122 | }
|
|---|
| 123 |
|
|---|
| 124 | urlpatterns = patterns('',
|
|---|
| 125 | # ... some generic view using info_dict
|
|---|
| 126 | ( r'^sitemap.xml$', 'django.contrib.sitemap.views.sitemap', {'sitemaps': sitemaps} )
|
|---|
| 127 | )
|
|---|
| 128 |
|
|---|
| 129 | .. _flatpages: http://www.djangoproject.com/documentation/flatpages/
|
|---|
| 130 | .. _sites: http://www.djangoproject.com/documentation/sites/
|
|---|
| 131 | .. _generic views: http://www.djangoproject.com/documentation/generic_views/
|
|---|
| 132 | .. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
|
|---|
| 133 |
|
|---|
| 134 | Creating a sitemap index
|
|---|
| 135 | ------------------------
|
|---|
| 136 |
|
|---|
| 137 | The sitemap framework also has the ability to create a sitemap index
|
|---|
| 138 | that references individual sitemap files, one per each section defined
|
|---|
| 139 | in your ``sitemaps`` dict. The only differences in usage are:
|
|---|
| 140 |
|
|---|
| 141 | * You use two views in your URLconf: ``django.contrib.sitemap.views.index``
|
|---|
| 142 | and ``django.contrib.sitemap.views.sitemap``
|
|---|
| 143 | * The ``django.contrib.sitemap.views.sitemap`` view should take a
|
|---|
| 144 | ``section`` keyword argument.
|
|---|
| 145 |
|
|---|
| 146 | Here is what the relevant URLconf lines would look like for the example above::
|
|---|
| 147 |
|
|---|
| 148 | ( r'^sitemap.xml$', 'django.contrib.sitemap.views.index', {'sitemaps': sitemaps} )
|
|---|
| 149 | ( r'^sitemap-(?P<section>.+).xml$', 'django.contrib.sitemap.views.sitemap', {'sitemaps': sitemaps} )
|
|---|
| 150 |
|
|---|
| 151 | This will automatically generate a ``sitemap.xml`` file that references
|
|---|
| 152 | both ``sitemap-flatpages.xml`` and ``sitemap-blog.xml``. The ``Sitemap``
|
|---|
| 153 | classes and the ``sitemaps`` dict don't change at all.
|
|---|
| 154 |
|
|---|
| 155 | Pinging Google
|
|---|
| 156 | --------------
|
|---|
| 157 |
|
|---|
| 158 | For sites with dynamic content, it may be desirable to "ping" Google when
|
|---|
| 159 | your sitemap changes, to let them know to re-index your site. The framework
|
|---|
| 160 | provides a function to do just that: ``ping_google()``. This will automatically
|
|---|
| 161 | determine your sitemap URL and send a ping to Google.
|
|---|
| 162 |
|
|---|
| 163 | One useful way to call ``ping_google()`` is from a model's ``save()`` method::
|
|---|
| 164 |
|
|---|
| 165 | from django.contrib.sitemap import ping_google
|
|---|
| 166 |
|
|---|
| 167 | def save(self):
|
|---|
| 168 | super(Entry, self).save()
|
|---|
| 169 | ping_google()
|
|---|