Caching sitemaps en django

Implementé una clase de mapa de sitio simple usando la aplicación de mapa de sitio predeterminada de django. Como tardó mucho tiempo en ejecutarse, agregué almacenamiento en caché manual:

class ShortReviewsSitemap(Sitemap): changefreq = "hourly" priority = 0.7 def items(self): # try to retrieve from cache result = get_cache(CACHE_SITEMAP_SHORT_REVIEWS, "sitemap_short_reviews") if result!=None: return result result = ShortReview.objects.all().order_by("-created_at") # store in cache set_cache(CACHE_SITEMAP_SHORT_REVIEWS, "sitemap_short_reviews", result) return result def lastmod(self, obj): return obj.updated_at 

El problema es que memcache solo permite un objeto máximo de 1MB. Este era más grande que 1MB, por lo que el almacenamiento en caché falló:

 >7 SERVER_ERROR object too large for cache 

El problema es que django tiene una forma automatizada de decidir cuándo debe dividir el archivo de sitemap en pequeños. Según los documentos ( http://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/ ):

Debería crear un archivo de índice si uno de sus mapas de sitio tiene más de 50,000 URL. En este caso, Django paginará automáticamente el mapa del sitio, y el índice lo reflejará.

¿Cuál crees que sería la mejor manera de habilitar el almacenamiento en caché de mapas de sitio? – Hackear en el marco de django sitemaps para restringir el tamaño de un único mapa del sitio a, digamos, 10,000 registros parece ser la mejor idea. ¿Por qué se eligieron 50,000 en primer lugar? ¿Consejos de Google? ¿número aleatorio? – ¿O tal vez hay una manera de permitir que los archivos de memcached almacenen archivos más grandes? – ¿O tal vez una vez guardados, los mapas de sitio deberían estar disponibles como archivos estáticos? Esto significaría que, en lugar de almacenar en caché con memcached, tendría que almacenar manualmente los resultados en el sistema de archivos y recuperarlos la próxima vez que se solicite el mapa del sitio (tal vez limpiando el directorio diariamente en un trabajo cron).

    Todos esos parecen un nivel muy bajo y me pregunto si existe una solución obvia …

    50k no es un parámetro hardcore. 🙂

    Puede usar esta clase en su lugar django.contrib.sitemaps.GenericSitemap

     class LimitGenericSitemap(GenericSitemap): limit = 2000 

    Suponiendo que no necesita todas esas páginas en su mapa del sitio y luego reducir el límite para reducir el tamaño del archivo funcionará bien como se describe en la respuesta anterior.

    Si desea un mapa del sitio muy grande y desea usar memcached, puede dividir el contenido en varios fragmentos, almacenarlos bajo claves individuales y luego volver a juntarlos nuevamente en la salida. Para hacer esto más eficiente, Memcached admite la capacidad de obtener varias claves al mismo tiempo, aunque no estoy seguro de que el cliente django admita esta capacidad todavía.

    Para referencia, el límite de 1MB es una característica de memcached que se relaciona con la forma en que almacena los datos: http://code.google.com/p/memcached/wiki/FAQ#What_is_the_maximum_data_size_you_can_store?_(1_megabyte)

    Puedes servir sitemaps también en formato gzip, lo que los hace mucho más pequeños. XML es adecuado perfectamente para la compresión gzip. Lo que a veces hago: crear el (los) archivo (s) de mapa del sitio comprimidos en un cronjob y renderizarlos tan a menudo como sea necesario. Por lo general, una vez al día será suficiente. El código para esto puede verse así. Solo asegúrese de tener su sitemap.xml.gz servido desde la raíz de su dominio:

      from django.contrib.sitemaps import GenericSitemap from django.contrib.sitemaps.views import sitemap from django.utils.encoding import smart_str import gzip sitemaps = { 'page': GenericSitemap({'queryset': MyModel.objects.all().order_by('-created'), 'date_field': 'created'}), } f = gzip.open(settings.STATIC_ROOT+'/sitemap.xml.gz', 'wb') f.write(smart_str(sitemap(request, sitemaps=sitemaps).render().content)) f.close() 

    Esto debería empezar.

    Tengo cerca de 200,000 páginas en mi sitio, así que tuve que tener el índice sin importar qué. Terminé haciendo el truco anterior, limitando el mapa del sitio a 250 enlaces y también implementando un caché basado en archivos.

    El algoritmo básico es este:

    • Intenta cargar el mapa del sitio desde un archivo en el disco
    • Si eso falla, genera el mapa del sitio, y
    • Si el mapa del sitio contiene 250 enlaces (el número establecido arriba), guárdelo en el disco y luego devuélvalo.

    El resultado final es que la primera vez que se solicita un mapa del sitio, si está completo, se genera y se guarda en el disco. La próxima vez que se solicite, simplemente se sirve desde el disco. Como mi contenido nunca cambia, esto funciona muy bien. Sin embargo, si quiero cambiar un mapa del sitio, es tan simple como eliminar los archivos del disco y esperar a que los rastreadores vuelvan a generar cosas.

    El código para todo está aquí, si está interesado: http://bitbucket.org/mlissner/legal-current-awareness/src/tip/alert/alertSystem/sitemap.py

    Tal vez esta sea una buena solución para ti también.