1. Artur Barseghyan
  2. django-images-sitemap

Commits

Artur Barseghyan  committed fa50468 Draft

initial

  • Participants
  • Branches default

Comments (0)

Files changed (8)

File .hgignore

View file
+syntax: glob
+*.pyc
+.hgignore~
+setup.py~

File readme.txt

View file
+AUTHOR
+    Artur Barseghyan (artur.barseghyan@gmail.com)
+
+VERSION
+    0.2 Beta. Ready for production.
+
+ABOUT / DESCRIPTION
+    Simple app to generate images sitemap. For more information about images sitemap see the
+    following links:
+        http://googlewebmastercentral.blogspot.com/2010/04/adding-images-to-your-sitemaps.html
+        http://www.google.com/support/webmasters/bin/answer.py?answer=178636
+
+INSTALLATION / USAGE / EXAMPLES
+    It's pretty much the same as simple Django sitemaps. You may need to add your template
+    directory (where the image_sitemap.xml file is located) to the ``TEMPLATE_DIRS`` in
+    the "settings.py".
+
+    IMPORTANT! If you supply your images sitemap to the Django sitemaps, it will treat it as
+    simple feed (not image feed). So, make it a separate URL in your "urls.py" and add that
+    URL to the "robots.txt", next to the general sitemap.
+
+    IMPORTANT! By default results are cached for 1 hour based on ``request.path``. If your
+    search results are somehow dependant on other criteria, make appropriate changes to
+    the "images_sitemap.xml" template.
+
+    IMPORTANT! By default URL of the current site is appended to the "location" (<loc>)
+    and "image_location" (<image:loc>). If you don't want it to happen, override the
+    following variables in your "settings.py" by setting them to False:
+        ``IMAGES_SITEMAP_PREPEND_LOC_URL_WITH_SITE_URL``
+        ``IMAGES_SITEMAP_PREPEND_IMAGE_LOC_URL_WITH_SITE_URL``
+
+    ##########################################
+    # See the following as complete example. #
+    ##########################################
+
+    ###############################
+    # Example images "sitemap.py" #
+    ###############################
+    from django.conf.urls.defaults import *
+    from images_sitemap import ImagesSitemap
+
+    from media.models import Photo
+    from news.models import Article
+
+    # Note, that picture_url is a property in your Photo model, which returns an absolute URL to the image file.
+    photo_info_dict = {
+        'queryset': Photo.objects.all(),
+        'image_location_field': 'url',
+        'image_title_field': 'title',
+        'location_field': 'url', # If your image does not have a detail page, provide just image URL.
+    }
+
+    article_images_info_dict = {
+        'queryset': Article.objects.all(),
+        'image_location_field': 'picture_url',
+    }
+
+    photos_sitemap = {
+        'photos': ImagesSitemap(photo_info_dict, priority=0.6),
+    }
+
+    article_images_sitemap = {
+        'article_images': ImagesSitemap(article_images_info_dict, priority=0.6),
+    }
+
+    #####################
+    # Example "urls.py" #
+    #####################
+    from ... import photos_sitemap
+    from ... import article_images_sitemap
+    from ... import events_sitemap, articles_sitemap
+
+    sitemap = {}
+    sitemap.update(events_sitemap)
+    sitemap.update(articles_sitemap)
+
+    urlpatterns = patterns('',
+        # some generic view using info_dict
+        # ...
+
+        # images sitemaps
+        (r'^sitemap-photos-images\.xml$', 'images_sitemap.views.render', {'sitemaps': photos_sitemap})
+        (r'^sitemap-news-images\.xml$', 'images_sitemap.views.render', {'sitemaps': article_images_sitemap})
+
+        # general sitemaps
+        (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}),
+        (r'^sitemap-(?P<section>.+)\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
+    )
+
+    ########################
+    # Example "robots.txt" #
+    ########################
+    Sitemap: /sitemap.xml
+    Sitemap: /sitemap-photos-images.xml
+    Sitemap: /sitemap-news-images.xml

File setup.py

View file
+"""
+AUTHOR: Artur Barseghyan
+    (artur.barseghyan@gmail.com)
+DESCRIPTION
+    Images XML sitemap for Django.
+"""
+
+import os
+from setuptools import setup, find_packages
+
+readme = open(os.path.join(os.path.dirname(__file__), 'readme.txt')).read()
+
+version = '0.2'
+
+setup(
+    name='images_sitemap',
+    version=version,
+    description=("Images XML sitemap for Django"),
+    long_description = readme,
+    classifiers=[
+        "Framework :: Django",
+        "Programming Language :: Python",
+        "Environment :: Web Environment",
+        'Intended Audience :: Developers',
+        'Operating System :: OS Independent',
+    ],
+    keywords='xml sitemap, images, django, app, python',
+    author='Artur Barseghyan',
+    author_email='artur.barseghyan@gmail.com',
+    url='https://bitbucket.org/barseghyanartur/django-images-sitemap',
+    package_dir={'':'src'},
+    packages=find_packages(where='./src'),
+)

File src/images_sitemap/__init__.py

View file
+"""
+@author Artur Barseghyan (artur.barseghyan@gmail.com)
+@copyright Artur Barseghyan
+Read the readme.txt file in the root of this app.
+"""
+
+from django.contrib.sitemaps import GenericSitemap
+
+from images_sitemap.conf import get_setting
+
+PREPEND_LOC_URL_WITH_SITE_URL = get_setting('PREPEND_LOC_URL_WITH_SITE_URL')
+PREPEND_IMAGE_LOC_URL_WITH_SITE_URL = get_setting('PREPEND_IMAGE_LOC_URL_WITH_SITE_URL')
+
+class ImagesSitemap(GenericSitemap):
+    """
+    Class for image sitemap. Implemented accordings to specs specifed by google.
+
+    @link http://www.google.com/support/webmasters/bin/answer.py?answer=178636
+    """
+    def __init__(self, info_dict, priority=None, changefreq=None):
+        self.image_location_field = info_dict.get('image_location_field', None)
+        self.image_caption_field = info_dict.get('image_caption_field', None)
+        self.image_title_field = info_dict.get('image_title_field', None)
+        self.image_geo_location_field = info_dict.get('image_geo_location_field', None)
+        self.image_license_field = info_dict.get('image_license_field', None)
+        self.location_field = info_dict.get('location_field', None)
+        super(ImagesSitemap, self).__init__(info_dict, priority, changefreq)
+
+    def image_location(self, item):
+        """
+        Gets our image location.
+        """
+        if self.image_location_field is not None:
+            return getattr(item, self.image_location_field)
+        return None
+
+    def image_caption(self, item):
+        """
+        Gets our image caption.
+        """
+        if self.image_caption_field is not None:
+            return getattr(item, self.image_caption_field)
+        return None
+
+    def image_title(self, item):
+        """
+        Gets our image title.
+        """
+        if self.image_title_field is not None:
+            return getattr(item, self.image_title_field)
+        return None
+
+    def image_geo_location(self, item):
+        """
+        Gets our image geo location.
+        """
+        if self.image_geo_location_field is not None:
+            return getattr(item, self.image_geo_location_field)
+        return None
+
+    def image_license(self, item):
+        """
+        Gets our image geo location.
+        """
+        if self.image_license_field is not None:
+            return getattr(item, self.image_license_field)
+        return None
+
+    def location(self, obj):
+        if self.location_field is not None:
+            try:
+                return getattr(obj, self.location_field)
+            except:
+                return None
+        return obj.get_absolute_url()
+
+    def __get(self, name, obj, default=None):
+        try:
+            attr = getattr(self, name)
+        except AttributeError:
+            return default
+        if callable(attr):
+            return attr(obj)
+        return attr
+
+    def get_urls(self, page=1):
+        from django.contrib.sites.models import Site
+        current_site = Site.objects.get_current()
+        urls = []
+        for item in self.paginator.page(page).object_list:
+            loc = self.__get('location', item, None)
+            if loc and PREPEND_LOC_URL_WITH_SITE_URL:
+                loc = "http://%s%s" % (unicode(current_site.domain), unicode(loc))
+
+            image_loc = self.__get('image_location', item, None)
+            if image_loc and PREPEND_IMAGE_LOC_URL_WITH_SITE_URL:
+                try:
+                    image_loc = "http://%s%s" % (unicode(current_site.domain), unicode(image_loc))
+                except Exception, e:
+                    continue
+
+            url_info = {
+                'location': loc,
+                'image_location': image_loc,
+                'image_caption': self.__get('image_caption', item, None),
+                'image_title': self.__get('image_title', item, None),
+                'image_license': self.__get('image_license', item, None),
+                'image_geo_location': self.__get('image_geo_location', item, None),
+                'lastmod': self.__get('lastmod', item, None),
+                'changefreq': self.__get('changefreq', item, None),
+                'priority': self.__get('priority', item, None)
+            }
+            urls.append(url_info)
+        return urls

File src/images_sitemap/conf.py

View file
+from django.conf import settings
+
+from images_sitemap import defaults
+
+def get_setting(setting, override=None):
+    """
+    Get a setting from ``images_sitemap`` conf module, falling back to the default.
+
+    If override is not None, it will be used instead of the setting.
+    """
+    if override is not None:
+        return override
+    if hasattr(settings, 'IMAGES_SITEMAP_%s' % setting):
+        return getattr(settings, 'IMAGES_SITEMAP_%s' % setting)
+    else:
+        return getattr(defaults, setting)

File src/images_sitemap/defaults.py

View file
+from django.conf import settings
+
+# When set to True, current site's domain is prepended to the location URL.
+PREPEND_LOC_URL_WITH_SITE_URL = True
+
+# When set to True, current site's domain is prepended to the image location URL.
+PREPEND_IMAGE_LOC_URL_WITH_SITE_URL = True
+
+DEBUG = settings.DEBUG

File src/images_sitemap/templates/images_sitemap/images_sitemap.xml

View file
+<?xml version="1.0" encoding="UTF-8"?>
+{% load cache %}
+{#% cache 3600 images_sitemap request.path %#}
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
+{% spaceless %}
+{% for url in urlset %}
+{% if url.image_location %}
+  <url>
+    {% if url.location %}<loc>{{ url.location }}</loc>{% endif %}
+    {% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
+    {% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
+    {% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
+    <image:image>
+        <image:loc>{{ url.image_location }}</image:loc>
+        {% if url.image_caption %}<image:caption>{{ url.image_caption }}</image:caption>{% endif %}
+        {% if url.image_title %}<image:title>{{ url.image_title }}</image:title>{% endif %}
+    </image:image>
+   </url>
+{% endif %}
+{% endfor %}
+{% endspaceless %}
+</urlset>
+{#% endcache %#}

File src/images_sitemap/views.py

View file
+"""
+AUTHOR
+    Artur Barseghyan (artur.barseghyan@gmail.com)
+
+DESCRIPTION
+    Read the readme.txt file in the root of this app.
+"""
+
+from django.http import HttpResponse, Http404
+from django.template import loader
+from django.utils.encoding import smart_str
+from django.core.paginator import EmptyPage, PageNotAnInteger
+
+def render(request, sitemaps, section=None, template_name='images_sitemap/images_sitemap.xml'):
+    """
+        Renders images sitemap.
+
+        @param HttpRequest request
+        @param sitemaps
+        @param secion
+        @param string template_name
+        @return HttpResponse
+    """
+    maps, urls = [], []
+    if section is not None:
+        if section not in sitemaps:
+            raise Http404("No sitemap available for section: %r" % section)
+        maps.append(sitemaps[section])
+    else:
+        maps = sitemaps.values()
+    page = request.GET.get("p", 1)
+    for site in maps:
+        try:
+            if callable(site):
+                urls.extend(site().get_urls(page))
+            else:
+                urls.extend(site.get_urls(page))
+        except EmptyPage:
+            raise Http404("Page %s empty" % page)
+        except PageNotAnInteger:
+            raise Http404("No page '%s'" % page)
+    xml = smart_str(loader.render_to_string(template_name, {'urlset': urls, 'request': request}))
+    return HttpResponse(xml, mimetype='application/xml')