站点地图和具有多个网址的对象

Ale*_*kov 16 python sitemap django

在Django中使用sitemap的常规方法是:

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)
Run Code Online (Sandbox Code Playgroud)

然后在学校模型中我们定义:

  def get_absolute_url(self):
      return reverse('schools:school_about', kwargs={'school_id': self.pk})
Run Code Online (Sandbox Code Playgroud)

在这种实现中,我在sitemap.xml中为一所学校提供了一个About链接

问题是我的学校有多个页面:关于,教师,学生和其他人,我希望所有要呈现的是sitemap.xml

这样做的最佳方法是什么?

Phi*_*lip 11

您可以处理items可能返回任何可以传递给其他方法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])()
Run Code Online (Sandbox Code Playgroud)

如果字段的数量和名称没有预先确定,我会采用一种完全动态的方法:允许模型有一个get_sitemap_urls返回绝对URL列表的方​​法,并使用Sitemap执行此方法的方法.也就是说,在最简单的情况下,您不需要访问priority/changefreq/lastmod方法中的对象:

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
Run Code Online (Sandbox Code Playgroud)