2010-01-17 24 views
8

Ho implementato una semplice classe Sitemap utilizzando l'app sitemap predefinita di Django. Come è stato tenuto un lungo periodo di tempo per l'esecuzione, ho aggiunto la cache manuale:Sitemap cache in 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 

Il problema è che memcache consente solo oggetto max 1MB. Questo era più grande che 1 MB, in modo da memorizzare nella cache non riuscita:

>7 SERVER_ERROR object too large for cache 

Il problema è che Django ha un modo automatico di decidere quando deve dividere il file sitemap in quelle smalled. Secondo la documentazione (http://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/):

È necessario creare un file di indice se uno dei tuoi Sitemap ha più di 50.000 URL. In questo caso, Django sarà che impagina automaticamente la sitemap, e l'indice lo rifletterà.

Quale pensi che sarebbe il modo migliore per abilitare la memorizzazione nella cache delle sitemap? - Hacking nel framework di sitemap django per limitare le dimensioni di una singola Sitemap a, diciamo, 10.000 record sembra l'idea migliore. Perché sono stati scelti 50.000 in primo luogo? Consiglio di Google? numero casuale? - O forse c'è un modo per consentire ai file di grandi dimensioni del negozio memcached? - O forse gli sforzi salvati, le sitemaps dovrebbero essere rese disponibili come file statici? Ciò significherebbe che invece di memorizzare nella cache con memcached dovrei memorizzare manualmente i risultati nel filesystem e recuperarli da lì la prossima volta quando viene richiesta la sitemap (magari pulendo la directory ogni giorno in un cron job).

Tutti coloro sembrano livello molto basso e mi chiedo se esiste una soluzione ovvia ...

+2

Non fare "risultato! = Nessuno", sempre fare "risultato non è nessuno" – stefanw

+1

perché è? qual è la differenza? – michuk

+0

50.000 è indicato nel protocollo Sitemaps. – webjunkie

risposta

13

50k non è un parametro hardcore. :)

È possibile utilizzare questa classe invece django.contrib.sitemaps.GenericSitemap

class LimitGenericSitemap(GenericSitemap): 
    limit = 2000 
+0

Questo è stato straordinariamente utile. Per una versione funzionante di questo, vedere il mio codice, qui: http://bitbucket.org/mlissner/legal-current-awareness/src/dc66d2268bec/alert/alertSystem/sitemap.py – mlissner

2

Dando per scontato che non hai bisogno di tutte quelle pagine nella tua sitemap quindi riducendo il limite per ottenere la dimensione del file in basso funzionerà bene come descritto nella risposta precedente.

Se si desidera una sitemap di grandi dimensioni e si desidera utilizzare memcached, è possibile suddividere il contenuto in più blocchi, archiviarli in singole chiavi e quindi reinserirli nuovamente in output. Per rendere più efficiente Memcached supporta la possibilità di ottenere più chiavi contemporaneamente, anche se non sono sicuro che il client django supporti ancora questa funzionalità.

Per riferimento al limite di 1 MB è una caratteristica di memcached a che fare con il modo in esso memorizza i dati: http://code.google.com/p/memcached/wiki/FAQ#What_is_the_maximum_data_size_you_can_store?_(1_megabyte)

1

Ho circa 200.000 pagine del mio sito, così ho dovuto avere l'indice di non importa quale. Ho finito per fare il trucco precedente, limitando la sitemap a 250 link e implementando anche una cache basata su file.

L'algoritmo di base è questa:

  • tenta di caricare la mappa del sito da un file su disco
  • Se non funziona, genera la mappa del sito, e
  • Se la mappa del sito contiene 250 collegamenti (il numero impostato sopra), salvarlo su disco e quindi restituirlo.

Il risultato finale è che la prima volta viene richiesta una mappa del sito, se è completa, viene generata e salvata su disco. La prossima volta che viene richiesto, viene semplicemente servito dal disco. Poiché il mio contenuto non cambia mai, funziona molto bene. Tuttavia, se voglio cambiare una Sitemap, è semplice come cancellare i file dal disco e aspettare che i crawler vengano rigenerati.

Il codice per il tutto è qui, se siete interessati: http://bitbucket.org/mlissner/legal-current-awareness/src/tip/alert/alertSystem/sitemap.py

Forse questa sarà una buona soluzione anche per voi.

1

Puoi pubblicare sitemap anche in formato gzip, il che le rende molto più piccole. XML è adatto perfettamente per la compressione gzip. Quello che a volte faccio: crea i file della Sitemap gzip in un cronjob e li esegui tutte le volte che è necessario. Di solito, una volta al giorno sarà sufficiente. Il codice per questo potrebbe assomigliare a questo. Basta fare in modo di avere il vostro sitemap.xml.gz servito dal tuo 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() 

Questo dovrebbe iniziare.