2010-01-17 30 views
8

Implementé una clase de sitemap simple usando la aplicación de mapa de sitio predeterminada de django. Ya que estaba tomando mucho tiempo para ejecutar, añadí el almacenamiento en caché Manual:Almacenamiento de sitemaps en django

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 permite único objeto máximo de 1 MB. Éste era más grande que 1 MB, 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 se debe dividir el archivo de mapa del sitio en smalled queridos. De acuerdo con la documentación (http://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/):

Debe crear un archivo de índice si uno de sus mapas de sitio cuenta con más de 50.000 URL. En este caso, Django va a paginar automáticamente el mapa del sitio, y el índice reflejará eso.

¿Cuál crees que sería la mejor manera de habilitar el almacenamiento en caché de sitemaps? - Hackear el marco de sitemaps de django para restringir un solo tamaño de mapa de sitio a, digamos, 10,000 registros parece ser la mejor idea. ¿Por qué se eligieron 50,000 en primer lugar? Consejo de Google? ¿número aleatorio? - ¿O tal vez hay una forma de permitir que la memoria de memcached almacene archivos más grandes? - ¿O tal vez se guardaron onces, los sitemaps 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 cuando se solicite el mapa del sitio (quizás limpiando el directorio diariamente en un trabajo cron).

Todos aquellos parecen muy bajo nivel y me pregunto si existe una solución obvia ...

+2

Do not do "result! = None", always do "result is not None" – stefanw

+1

¿por qué es eso? ¿cual es la diferencia? – michuk

+0

50,000 se da en el protocolo Sitemaps. – webjunkie

Respuesta

13

50k no es un parámetro hardcore. :)

Se puede utilizar esta clase en lugar django.contrib.sitemaps.GenericSitemap

class LimitGenericSitemap(GenericSitemap): 
    limit = 2000 
+0

Esto fue fenomenalmente útil. Para una versión de trabajo de esto, vea mi código, aquí: http://bitbucket.org/mlissner/legal-current-awareness/src/dc66d2268bec/alert/alertSystem/sitemap.py – mlissner

2

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

Si desea un mapa del sitio muy grande y desea utilizar memcached, puede dividir el contenido en varios trozos, almacenarlos en claves individuales y luego volver a armarlos 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 si el cliente django aún admite esta capacidad.

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

1

Tengo alrededor de 200.000 páginas en mi sitio, por lo que tenía que tener el índice de no importa 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 el siguiente:

  • intenta cargar el mapa del sitio de un archivo en el disco
  • Si eso no funciona, genera el mapa del sitio, y
  • Si el mapa contiene 250 enlaces (el número configurado 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 regenerar las cosas.

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

Tal vez esto será una buena solución para usted también.

1

Puede publicar sitemaps también en formato gzip, lo que los hace mucho más pequeños. XML se adapta perfectamente a la compresión gzip. Lo que a veces hago: crea los archivos del mapa del sitio con gzip en un cronjob y renderízalos con la frecuencia que sea necesaria. Por lo general, una vez al día será suficiente. El código para esto puede verse así. Sólo asegúrese de tener su sitemap.xml.gz servido desde su raíz del 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.

Cuestiones relacionadas