2010-01-17 8 views
8

J'ai implémenté une classe de sitemap simple en utilisant l'application sitemap par défaut de django. Comme il prenait beaucoup de temps pour exécuter, j'ai ajouté la mise en cache manuelle:Mise en cache de sitemaps dans 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 

Le problème est que memcache permet seul objet max 1Mo. Celui-ci était plus grand que 1 Mo, pour le stockage dans le cache a échoué:

>7 SERVER_ERROR object too large for cache 

Le problème est que django a un moyen automatisé de décider quand il doit diviser le fichier sitemap dans les smalled. Selon les docs (http://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/):

Vous devez créer un fichier d'index si l'un de vos sitemaps a plus de 50.000 URL. Dans ce cas, Django paginera automatiquement le sitemap, et l'index reflétera cela.

Selon vous, quel serait le meilleur moyen d'activer les sitemaps de mise en cache? - Hacker dans le framework django sitemaps pour restreindre une taille de sitemap unique à, disons, 10 000 enregistrements semble être la meilleure idée. Pourquoi 50 000 personnes ont-elles été choisies en premier lieu? Conseil Google? nombre aléatoire? - Ou peut-être y a-t-il un moyen de permettre aux memcached de stocker de plus gros fichiers? - Ou peut-être sauvegardés, les sitemaps devraient être disponibles sous forme de fichiers statiques? Cela signifierait qu'au lieu de mettre en mémoire cache avec memcached, je devrais stocker manuellement les résultats dans le système de fichiers et les récupérer la prochaine fois que le sitemap est demandé (peut-être nettoyer le répertoire quotidiennement dans un travail cron).

Tous ceux qui semblent très bas niveau et je me demande si une solution évidente existe ...

+2

Ne faites pas "résultat! = Aucun", faites toujours "le résultat n'est pas Aucun" – stefanw

+1

pourquoi est-ce? quelle est la différence? – michuk

+0

50 000 est donné dans le protocole Sitemaps. – webjunkie

Répondre

13

50k ce n'est pas un paramètre hardcore. :)

Vous pouvez utiliser cette classe à la place django.contrib.sitemaps.GenericSitemap

class LimitGenericSitemap(GenericSitemap): 
    limit = 2000 
+0

C'était phénoménalement utile. Pour une version de travail, voir mon code, ici: http://bitbucket.org/mlissner/legal-current-awareness/src/dc66d2268bec/alert/alertSystem/sitemap.py – mlissner

2

En supposant que vous n'avez pas besoin de toutes ces pages dans votre sitemap réduisant alors la limite pour obtenir la taille du fichier fonctionnera bien comme décrit dans la réponse précédente.

Si vous voulez un sitemap très volumineux et que vous voulez utiliser memcached, vous pouvez diviser le contenu en plusieurs blocs, les stocker sous des clés individuelles, puis les réassembler en sortie. Pour rendre cela plus efficace Memcached supporte la possibilité d'obtenir plusieurs clés en même temps, bien que je ne sache pas si le client django supporte encore cette capacité.

Pour référence la limite 1Mo est une caractéristique de memcached à voir avec la façon dont il stocke les données: http://code.google.com/p/memcached/wiki/FAQ#What_is_the_maximum_data_size_you_can_store?_(1_megabyte)

1

J'ai environ 200 000 pages sur mon site, donc je devais avoir l'indice, peu importe quoi. J'ai fini par faire le hack ci-dessus, en limitant le sitemap à 250 liens, et en implémentant également un cache basé sur des fichiers.

L'algorithme de base est la suivante:

  • Essayez de charger le plan du site à partir d'un fichier sur le disque
  • Si cela échoue, générer le plan du site, et
  • Si le plan du site contient 250 liens (le nombre ci-dessus), enregistrez-le sur le disque, puis renvoyez-le.

Le résultat final est que la première fois qu'un sitemap est demandé, s'il est terminé, il est généré et enregistré sur le disque. La prochaine fois qu'il est demandé, il est simplement servi à partir du disque. Puisque mon contenu ne change jamais, cela fonctionne très bien. Cependant, si je veux changer un sitemap, c'est aussi simple que de supprimer le (s) fichier (s) du disque, et d'attendre que les robots viennent régénérer les choses.

Le code de la chose est ici, si vous êtes intéressé: http://bitbucket.org/mlissner/legal-current-awareness/src/tip/alert/alertSystem/sitemap.py

Peut-être que ce sera une bonne solution pour vous aussi.

1

Vous pouvez également utiliser des sitemaps au format gzip, ce qui les rend beaucoup plus petits. XML est parfaitement adapté à la compression gzip. Ce que je fais parfois: Créez le (s) fichier (s) de sitemap gzippé (s) dans un cronjob et restaurez-les aussi souvent que nécessaire. Habituellement, une fois par jour suffira. Le code pour cela peut ressembler à ceci. Assurez-vous d'avoir votre sitemap.xml.gz servi à partir de la racine de votre domaine:

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() 

Cela devrait vous aider à démarrer.