Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sitemap and object with multiple urls

The normal way sitemap is used in Django is:

from django.contrib.sitemaps import Sitemap
from schools.models import School


class SchoolSitemap(Sitemap):
    changefreq = "weekly"
    priority = 0.6

    def items(self):
        return School.objects.filter(status = 2)

and then in the model of School we define:

  def get_absolute_url(self):
      return reverse('schools:school_about', kwargs={'school_id': self.pk})

In such implementation I have one About link for one school in sitemap.xml

The problem is that my school has multiple pages: About, Teachers, Pupils and others and I would like all of the to be rendered is sitemap.xml

What is the best approach to do it?

like image 714
Alexander Tyapkov Avatar asked Feb 12 '17 11:02

Alexander Tyapkov


People also ask

How many URLs can a sitemap have?

Break up large sitemaps into smaller sitemaps: a sitemap can contain up to 50,000 URLs and must not exceed 50MB uncompressed.

Can a website have multiple sitemaps?

Yes, you can! You might want to have multiple Sitemap files in a single directory for a number of reasons. For instance, if you have an auction site, you might want to have a daily Sitemap with new auction offers and a weekly Sitemap with less time-sensitive URLs.

Should I have multiple sitemaps?

Why You Need Multiple Sitemaps. The main reason why you should consider adding more than one sitemaps is not only to minimize crowding of links, but also to ensure that all pages are crawled and indexed by the search engines. Multiple sitemaps are very efficient in classifying and categorizing the content in a website.


1 Answers

You can work with the fact that items may return anything that can be passed to the other methods of a Sitemap:

import itertools

class SchoolSitemap(Sitemap):
    # List method names from your objects that return the absolute URLs here
    FIELDS = ("get_absolute_url", "get_about_url", "get_teachers_url")

    changefreq = "weekly"
    priority = 0.6

    def items(self):
        # This will return you all possible ("method_name", object) tuples instead of the
        # objects from the query set. The documentation says that this should be a list 
        # rather than an iterator, hence the list() wrapper.
        return list(itertools.product(SchoolSitemap.FIELDS,
                                      School.objects.filter(status = 2)))

    def location(self, item):
        # Call method_name on the object and return its output
        return getattr(item[1], item[0])()

If the number and names of fields are not predetermined, I would go for a completely dynamic approach: Allow models to have a get_sitemap_urls method that returns a list of absolute URLs, and use a Sitemap that executes this method. That is, in the simplest case where you do not need to have access to the objects in the priority/changefreq/lastmod methods:

class SchoolSitemap(Sitemap):
    changefreq = "weekly"
    priority = 0.6

    def items(self):
        return list(
             itertools.chain.from_iterable(( object.get_sitemap_urls()
                                             for object in 
                                             School.objects.filter(status = 2)))
        )

    def location(self, item):
        return item
like image 108
Phillip Avatar answered Oct 14 '22 15:10

Phillip