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 -> Todo
sebagai 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 Bang3
sudah 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 Project
dari basis data pada dasarnya tidak terhindarkan. Anda perlu titik untuk memulai. Namun, karena last_modified
ini 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_key
masih 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 Foo
atas - 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_key
dalam template ini. Itu tidak layak, karena seperti yang Anda katakan dalam pertanyaan, body
telah 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: Bar1
dan Bar2
diambil 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: Bang3
dan Bang4
diambil 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_parser
dihindari 3 kali: Bang1
, Bang2
, danBang4
Dan tentu saja, lain kali dilihat, Foo.cache_key
akan ditemukan, jadi satu-satunya biaya untuk rendering adalah mengambil Foo
sendiri dari database dan meminta cache.