Django sitemap index example
Asked Answered
K

3

7

I have following models relation:

class Section(models.Model):
    section = models.CharField(max_length=200, unique=True)
    name = models.CharField(max_length=200, blank = True)


class Article (models.Model):
    url = models.CharField(max_length = 30, unique=True)
    is_published = models.BooleanField()  
    section = models.ForeignKey(Section)

I need to create a sitemap for articles, which contains sitemap files for sections. I was reading django documentation about it here http://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/

But didn't manage to find answer how can I:

  1. Define sitemap class in this case
  2. How can I pass section parameters into url file (as it's explained in the docs)
  3. From where can I get {'sitemaps': sitemaps} if I defined sitemap as a python class in another file in the application
Kipp answered 8/9, 2009 at 6:44 Comment(2)
Your question is not at all clear. 1. Define it as described in the docs. What are you not clear about? 2. What parameters? What url file - do you mean urls.py? This has nothing to do with a sitemap. 3. You import it, like you would with any other code that you define in a different file.Protozoon
But, to create a section sitemap I need to implement filter. Something like this: Acrticle.objects.filter(section = Section.objects.get(section = section)) Not sure where should I implement the filterKipp
N
6

If i understand correctly you want to use sitemap index that would point at seperate sitemap xml files each for every section.

Django supports this feature by providing a separate sitemap view for index sitemaps.

Haven't used that feature before but something like the following would probably work in your case.

### sitemaps.py
from django.contrib.sitemaps import GenericSitemap
from models import Section

all_sitemaps = {}
for section in Section.objects.all():

    info_dict = {
        'queryset': section.article_set.filter(is_published=True),
    }

    sitemap = GenericSitemap(info_dict,priority=0.6)

    # dict key is provided as 'section' in sitemap index view
    all_sitemaps[section.name] = sitemap

### urls.py
from sitemaps import all_sitemaps as sitemaps

...
...
...

urlpatterns += patterns('',
        (r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}),
        (r'^sitemap-(?P<section>.+)\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
)
Neigh answered 8/9, 2009 at 18:28 Comment(0)
T
4
Django==2.2
Python==3.6

Here is the better and easy way to use sitemap index in Django, install django.contrib.sitemaps in the project by adding it to INSTALLED_APPS of settings.py. Write sitemaps.py file in your apps and define classes as you need. Example extend django.contrib.sitemap.Sitemap in StaticViewSitemap sitemap class for static URLs, make sure your all static URL has the name for reverse lookup(getting URL from URL name)

# app/sitemap.py

from django.contrib import sitemaps
from django.urls import reverse

class StaticViewSitemap(sitemaps.Sitemap):
    priority = 0.6
    changefreq = 'monthly'

    def items(self):
        # URLs names
        return ['index', 'aboutus', 'ourstory',]

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

Import all sitemaps in urls.py import sitemap and index from django.contrib.sitemaps.views then create a dictionary with sitemaps

# urls.py

from django.contrib.sitemaps.views import sitemap, index
from app.sitemaps import StaticViewSitemap

# add as many as sitemap you need as one key
sitemaps = {
    "static" : StaticViewSitemap,
}
urlpatterns = [

    # sitemap.xml index will have all sitemap-......xmls index
    path('sitemap.xml', index, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.index'),

    # sitemap-<section>.xml here <section> will be replaced by the key from sitemaps dict
    path('sitemap-<section>.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
]

Here you will have two sitemaps 1. sitemaps.xml 2. sitemaps-static.xml Run server open URL: http://localhost:8000/sitemap.xml

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc>http://127.0.0.1:8000/sitemap-static.xml</loc>
    </sitemap>
</sitemapindex>

Django automatically created an index of sitemaps now open URL: http://127.0.0.1:8000/sitemap-static.xml

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>http://localhost:8000/</loc>
        <changefreq>monthly</changefreq>
        <priority>0.6</priority>
    </url>
    <url>
        <loc>http://localhost:8000/about-us</loc>
        <changefreq>monthly</changefreq>
        <priority>0.6</priority>
    </url>
    <url>
        <loc>http://localhost:8000/our-story</loc>
        <changefreq>monthly</changefreq>
        <priority>0.6</priority>
    </url>
</urlset>
Tarrel answered 19/10, 2019 at 5:48 Comment(0)
L
1

For me, the accepted answer was impacting development and testing cycle speed since it made python manage.py commands run more slowly -- I had a little more to do in the DB than this example.

Here are the changes I made to mitigate (adapted to the example). Have yet to battle test it but this seems to do the trick (Python3):

### sitemaps.py

class SitemapLookup():
    """
    Instantiated class replaces the dictionary of {'sitemap-section': Sitemap} for urls.py
    Speeds up application load time by only querying the DB when a sitemap is first requested.
    """

    def __init__(self):
        self.sitemaps = {}

    def __iter__(self):
        self._generate_sitemaps_dict()
        return self.sitemaps.__iter__()

    def __getitem__(self, key):
        self._generate_sitemaps_dict()
        return self.sitemaps[key]

    def items(self):
        self._generate_sitemaps_dict()
        return self.sitemaps.items()

    def _generate_sitemaps_dict(self):
        if self.sitemaps:
            return
        for section in Section.objects.all():
            info_dict = {
                'queryset': section.article_set.filter(is_published=True),
            }
            # dict key is provided as 'section' in sitemap index view
            self.sitemaps[section.name] = GenericSitemap(info_dict, priority=0.6)



### urls.py
from sitemaps import SitemapLookup

...
...
...

sitemaps = SitemapLookup()

urlpatterns += patterns('',
        (r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}),
        (r'^sitemap-(?P<section>.+)\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
)
Luisluisa answered 1/5, 2017 at 19:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.