Önceden yüklenmiş tek bir nesnenin düz bir dökümünü önbelleğe almak için, evet, hiçbir şey kazanmazsınız. Bu örneklerin tarif ettiği şey bu değildir - daha düşük bir şeyde yapılacak herhangi bir değişikliğin hiyerarşide daha yüksek olan her şey için bir güncelleme başlatması gereken bir hiyerarşiyi tanımlarlar.
İlk örnek, 37 işaret bloğundan, Project -> Todolist -> Todo
hiyerarşi olarak kullanılır. Doldurulmuş bir örnek şöyle görünebilir:
Project: Foo (last_modified: 2014-05-10)
Todolist: Bar1 (last_modified: 2014-05-10)
Todo: Bang1 (last_modified: 2014-05-09)
Todo: Bang2 (last_modified: 2014-05-09)
Todolist: Bar2 (last_modified: 2014-04-01)
Todo: Bang3 (last_modified: 2014-04-01)
Todo: Bang4 (last_modified: 2014-04-01)
Diyelim ki Bang3
güncellendi. Tüm ebeveynleri de güncellenir:
Project: Foo (last_modified: 2014-05-16)
Todolist: Bar2 (last_modified: 2014-05-16)
Todo: Bang3 (last_modified: 2014-05-16)
Daha sonra oluşturma zamanı geldiğinde Project
, veritabanından yükleme temel olarak kaçınılmazdır. Başlamak için bir noktaya ihtiyacınız var. Ancak, tüm çocuklarınınlast_modified
bir göstergesi olduğundan, çocukları yüklemeye çalışmadan önce önbellek anahtarı olarak kullandığınız şey budur.
Blog gönderileri ayrı şablonlar kullanırken, bunları bir araya getireceğim. Umarım tüm etkileşimi tek bir yerde görmek onu biraz daha açık hale getirecektir.
Django şablonu şöyle görünebilir:
{% cache 9999 project project.cache_key %}
<h2>{{ project.name }}<h2>
<div>
{% for list in project.todolist.all %}
{% cache 9999 todolist list.cache_key %}
<ul>
{% for todo in list.todos.all %}
<li>{{ todo.body }}</li>
{% endfor %}
</ul>
{% endcache %}
{% endfor %}
</div>
{% endcache %}
Diyelim ki cache_key
hala önbellekte bulunan bir projeye katıldık. İlgili tüm nesnelerde değişiklikleri üst öğeye yaydığımız için, söz konusu anahtarın hala mevcut olması, oluşturulan tüm içeriğin önbellekten alınabileceği anlamına gelir .
Belirli bir Proje daha yeni güncellenmişse (örneğin, Foo
yukarıdaki gibi), o zaman çocuklarını oluşturması gerekir ve ancak o zaman o Proje için tüm Todolists için sorguyu çalıştırır. Aynı şekilde belirli bir Todolist için - eğer bu listenin cache_key'i varsa, içindeki todos değişmez ve her şey önbellekten çekilebilir.
Ayrıca todo.cache_key
bu şablonda nasıl kullanmadığımı da fark et. Buna değmez, çünkü soruda söylediğin gibi body
, zaten veritabanından çekildi. Ancak, bir şeyi önbelleğe almanın tek nedeni veritabanı isabetleri değildir. Örneğin, ham biçimlendirme metni (StackExchange'te soru / cevap kutularına yazdıklarımız gibi) almak ve HTML'ye dönüştürmek, sonucun önbelleğe alınmasının daha verimli olması için yeterli zaman alabilir.
Öyleyse, şablondaki iç döngü daha çok benzeyebilir:
{% for todo in list.todos.all %}
{% cache 9999 todo todo.cache_key %}
<li>{{ todo.body|expensive_markup_parser }}</li>
{% endcache %}
{% endfor %}
Her şeyi bir araya getirmek için, bu cevabın üstündeki orijinal verilerime geri dönelim. Eğer varsayarsak:
- Tüm nesneler orijinal hallerinde önbelleğe alınmıştı
Bang3
yeni güncellendi
- Değiştirilen şablonu oluşturuyoruz (dahil
expensive_markup_parser
)
O zaman her şey böyle yüklenecekti:
Foo
veritabanından alınır
Foo.cache_key
(2014-05-16) önbellekte mevcut değil
Foo.todolists.all()
sorgulanır: Bar1
ve Bar2
veritabanından alınır
Bar1.cache_key
(2014-05-10) önbellekte zaten var ; al ve ver
Bar2.cache_key
(2014-05-16) önbellekte mevcut değil
Bar2.todos.all()
sorgulanır: Bang3
ve Bang4
veritabanından alınır
Bang3.cache_key
(2014-05-16) önbellekte mevcut değil
{{ Bang3.body|expensive_markup_parser }}
işlendi
Bang4.cache_key
(2014-04-01) önbellekte zaten var ; al ve ver
Bu küçük örnekte önbellekten tasarruflar:
- Veritabanı isabetinden kaçınıldı:
Bar1.todos.all()
expensive_markup_parser
kaçınılması 3 kez: Bang1
, Bang2
, veBang4
Ve elbette, bir dahaki sefere görüntülendiğinde, Foo.cache_key
bulunacaktı, bu yüzden oluşturmanın tek maliyeti Foo
veritabanından tek başına almak ve önbelleği sorgulamak.