Untuk melakukan caching dump langsung dari satu objek yang sudah dimuat, ya, Anda tidak mendapatkan apa-apa atau hampir tidak ada. Bukan itu yang dijelaskan oleh contoh-contoh itu - mereka menggambarkan hierarki, di mana setiap perubahan ke sesuatu yang lebih rendah juga harus memicu pembaruan untuk segala sesuatu yang lebih tinggi dalam hierarki.
Contoh pertama, dari blog 37signals, digunakan Project -> Todolist -> Todosebagai hierarki. Contoh populasi mungkin terlihat seperti ini:
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)
Jadi, katakanlah Bang3sudah diperbarui. Semua orang tuanya juga mendapatkan pembaruan:
Project: Foo (last_modified: 2014-05-16)
Todolist: Bar2 (last_modified: 2014-05-16)
Todo: Bang3 (last_modified: 2014-05-16)
Maka ketika tiba saatnya untuk merender, memuat Projectdari basis data pada dasarnya tidak terhindarkan. Anda perlu titik untuk memulai. Namun, karena last_modifiedini merupakan indikator semua anak-anaknya , itulah yang Anda gunakan sebagai kunci cache sebelum mencoba memuat anak-anak.
Sementara posting blog menggunakan templat terpisah, saya akan menyatukannya menjadi satu. Semoga melihat interaksi yang lengkap di satu tempat akan membuatnya sedikit lebih jelas.
Jadi, template Django mungkin terlihat seperti ini:
{% 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 %}
Katakanlah kita lulus dalam Proyek yang cache_keymasih ada di cache. Karena kami menyebarkan perubahan ke semua objek terkait ke induk, fakta bahwa kunci tertentu masih ada berarti seluruh konten yang diberikan dapat ditarik dari cache.
Jika Proyek tertentu itu baru saja diperbarui - misalnya, seperti di Fooatas - maka ia harus membuat anak-anaknya, dan hanya kemudian akan menjalankan permintaan untuk semua Todolists untuk Proyek itu. Demikian juga untuk Todolist tertentu - jika cache_key daftar itu ada, maka todos di dalamnya belum berubah, dan semuanya dapat ditarik dari cache.
Perhatikan juga bagaimana saya tidak menggunakan todo.cache_keydalam template ini. Itu tidak layak, karena seperti yang Anda katakan dalam pertanyaan, bodytelah ditarik dari basis data. Namun, hit basis data bukan satu-satunya alasan Anda menyimpan sesuatu. Sebagai contoh, mengambil teks markup mentah (seperti apa yang kita ketik ke dalam kotak pertanyaan / jawaban di StackExchange) dan mengonversinya menjadi HTML mungkin memerlukan waktu yang cukup agar hasil cache lebih efisien.
Jika demikian, loop dalam template mungkin terlihat lebih seperti ini:
{% for todo in list.todos.all %}
{% cache 9999 todo todo.cache_key %}
<li>{{ todo.body|expensive_markup_parser }}</li>
{% endcache %}
{% endfor %}
Jadi, untuk menyatukan semuanya, mari kembali ke data asli saya di bagian atas jawaban ini. Jika kita mengasumsikan:
- Semua objek telah di-cache dalam keadaan aslinya
Bang3 baru saja diperbarui
- Kami sedang merender template yang dimodifikasi (termasuk
expensive_markup_parser)
Maka ini adalah bagaimana semuanya akan dimuat:
Foo diambil dari database
Foo.cache_key (2014-05-16) tidak ada di cache
Foo.todolists.all()dipertanyakan: Bar1dan Bar2diambil dari basis data
Bar1.cache_key(2014-05-10) sudah ada di cache ; ambil dan keluarkan
Bar2.cache_key (2014-05-16) tidak ada di cache
Bar2.todos.all()dipertanyakan: Bang3dan Bang4diambil dari basis data
Bang3.cache_key (2014-05-16) tidak ada di cache
{{ Bang3.body|expensive_markup_parser }} diberikan
Bang4.cache_key(2014-04-01) sudah ada di cache ; ambil dan keluarkan
Penghematan dari cache dalam contoh kecil ini adalah:
- Hit basis data dihindari:
Bar1.todos.all()
expensive_markup_parserdihindari 3 kali: Bang1, Bang2, danBang4
Dan tentu saja, lain kali dilihat, Foo.cache_keyakan ditemukan, jadi satu-satunya biaya untuk rendering adalah mengambil Foosendiri dari database dan meminta cache.