如何告诉 Django 将媒体 (pdf) 文件 url 放入 sitemap.xml?

How to tell Django to put media (pdf) files urls in sitemap.xml?

我已将静态视图和模型视图放入我的 Django 生成的 sitemap.xml 文件中,但我不知道如何告诉 Django 将所有媒体文件放入其中?我有一百个带有 seo 友好链接的 PDF 文件,我希望它们在我的 sitemap.xml 中,但由于它们与我的任何模型都不相关,我不知道如何管理它?

编辑:我几乎忘记了一件重要的事情——我的媒体 (pdf) 文件是通过 CloudFront 提供的,所以即使我设法以某种方式在我的 Django 中列出它们 Sitemap.xml 我还会遇到其他问题,因为它们有'something.cloudfront.com' 在他们的 url 中,而不是在我的网站 url 'example.com' 中。 这甚至有可能解决吗?这对 SEO 有何影响?

已解决: @kb,感谢您的出色回答!正如您在回答的第一部分中所建议的那样,我在我的 htaccess 中使用了 RewriteRule,它工作正常。 从第二部分开始,而不是为我的媒体文件创建模型(这会工作得很好,但唯一的缺点是手动添加每个新的 pdf 文件) 我决定在我的 items() 方法中添加一些行,这样我就可以列出存储桶内容并过滤 pdf 文件。有了它,我可以随时轻松地使我的所有文件保持最新状态:

#sitemap.py
import boto
from boto.s3.key import Key
from boto.s3.connection import S3Connection
import re

def items(self):    
        AWS_ACCESS_KEY_ID = #'my_access_key_number'
        AWS_SECRET_ACCESS_KEY = #'my_secret_access_key'
        Bucketname = #'my_bucket_name'
        conn = boto.s3.connect_to_region('eu-central-1', aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY, is_secure=False, calling_format = boto.s3.connection.OrdinaryCallingFormat())
        bucket = conn.get_bucket(Bucketname)
        new_list = []
        regex = re.compile(r'bucketsubfolder/media.*\.pdf$', re.I) #i hold my media files in bucketsubfolder so url is for example somedomain.cloudfront.net/bucketsubfolder/media/somefile.pdf
        for item in bucket.list():
            if regex.match(item.name):
                new_list.append(item.name)
        return new_list

您不能在您的站点地图中使用外部 URL(或者更确切地说,它们将不会产生预期的效果,不会被 Google 索引为您站点内容的一部分)。

我认为您最好的选择是在您的站点上专门设置一个路径,例如 /hosted/pdf/xxxx.pdf,将所有内容重写为 cloudfront.com/pdf/xxxx.pdf 或使用 mod_rewrite/location patterns/regex.[=20 的类似路径=]

这样您就可以在站点地图中使用本地站点 URL,但浏览器仍会直接将内容发送到云端,我认为这甚至可以很好地利用 302 HTTP 状态代码。

Sitemap class 中有一个 items() 方法 returns 要包含在 sitemap.xml 中的内容,您可以创建自己的拥有 class 扩展它并添加额外的数据。

您可以手动添加方法中硬编码的数据,但我认为首选的选择是创建一个模型来表示每个远程托管文件并包含在站点地图中输出它所需的信息。 (这还允许您在每个文件的基础上添加可见性等属性,并允许您通过管理员管理它,假设您为其设置了 ModelAdmin。)

我认为您可以使用扩展 SitemapBlogSitemap class 来执行类似于他们在 http://docs.djangoproject.com/en/1.9/ref/contrib/sitemaps 中显示的操作。请务必同时检查该页面上的标题 "Sitemap for static views"。

我的建议是您选择模型方法来表示文件,因此您将托管的 PDF(或其他 CDN 内容)作为名为 StaticHostedFile 或类似模型的模型,然后在items() 部分。它确实需要您索引所有当前的 PDF 来为它们创建模型,并在添加新 PDF 时创建新模型(但这可以自动化)。

很高兴知道您可以在 sitemap.xml 中添加 "includes",这样您就可以将站点内容拆分为两个站点地图(内容 + pdf)并将两者都包含在 sitemap.xml,例如:

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc>http://www.example.com/original_sitemap.xml</loc>
        <lastmod>2016-07-12T09:12Z</lastmod>
    </sitemap>
    <sitemap>
        <loc>http://www.example.com/pdf_sitemap.xml</loc>
        <lastmod>2016-07-15T08:55Z</lastmod>
    </sitemap>
</sitemapindex>

虽然这仍然需要本地 URLs 并按照上述重写,但是当您有多个单独的站点地图要组合时,这可能是一个绝妙的技巧。 (例如,如果 运行 一个子目录下的 Django 站点和另一个子目录下的 Wordpress 站点。)