views:

20

answers:

2

Hi,

I'm setting up some Django sitemaps. It works really well for all the objects I have, but I'm curious about how I should do it if I'd like to put something in the sitemap that has no object associated with it.

For instance, I have a category listing, and I can just return a queryset of all categories. URLs would be example.com/cats/12 or what have you. I also have a sort of pseudo root category that isn't associated with a category object. That page (example.com/cats/) is just a view that includes all sub categories with no parent, and a list of products. Point is, I can't use get_absolute_url because there is no "root" object. My solution was to get the queryset as a list, add a "None" object, then get the appropriate URL:

class CatsSitemap(Sitemap):
    changefreq = "weekly"
    priority = 0.4

    def items(self):
        cats = list(Category.objects.all())
        cats.append(None)
        return cats

    def location(self, obj):
        if(obj != None):
            return reverse('cats_sub_category', args=[obj.pk])
        else:
            return reverse('cats_root')

Does anyone see a problem with this? Will returning them as a list kill performance? Realistically we'll have perhaps hundreds of categories, but probably not many more than that. Too much?

+1  A: 

Maybe I found a better way to do it, which will certainly be useful in the future with other named views that don't have associated objects. In a sitemaps.py, put:

class NamedURLSitemap(Sitemap):
    priority = 1.0
    changefreq = "daily"

    def __init__(self, names):
        self.names = names

    def items(self):
        return self.names

    def lastmod(self, obj):
        return datetime.datetime.now()

    def location(self, obj):
        return reverse(obj)

And in the urls.py, put:

'cat-roots': NamedURLSitemap(['cats_root']),

This simplifies the Sitemap code for categories:

class CatsSitemap(Sitemap):
    changefreq = "weekly"
    priority = 0.4

    def items(self):
        return Category.objects.all()

    def location(self, obj):
        return reverse('cats_sub_category', args=[obj.pk])

Any opinion on this or the former solution?

CaptainThrowup
Seems like a pretty good solution to me. You should see about getting this included in django's sitemaps module, I think this is pretty universally useful. I'm not sure about using datetime.datetime.now() as the lastmod timestamp though
Chris Lawlor
You might make 'priority' and 'changefreq' parameters to __init__ though, to support adding multiple named pages with different priorities and changefreqs
Chris Lawlor
A: 

Slight improvement to your answer which includes the priority and changefreq for each page as part of the list passed to init:

class NamedURLSitemap(Sitemap):

    def __init__(self, pages):
        """
        Parameters:
        ``pages``
            A list of three-tuples containing name, priority, and changefreq:

            e.g. [('home', 0.5, 'daily'), ('search', 0.5, 'never')]
        """
        self.pages = pages

    def items(self):
        return self.pages

    def lastmod(self, obj):
        return datetime.datetime.now()

    def location(self, obj):
        return reverse(obj[0])

    def priority(self, obj):
        return obj[1]

    def changefreq(self, obj):
        return obj[2]
Chris Lawlor