Для кешування прямого дампа одного вже завантаженого об'єкта, так, ви нічого не отримуєте, або майже нічого. Це не те, що описують ці приклади - вони описують ієрархію, де будь-яка зміна на щось нижче також повинна викликати оновлення до всього, що знаходиться вище в ієрархії.
Перший приклад із блогу 37signals використовує Project -> Todolist -> Todo
як ієрархію. Населений приклад може виглядати приблизно так:
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)
Отже, скажімо, Bang3
оновлено. Усі його батьки також оновлюються:
Project: Foo (last_modified: 2014-05-16)
Todolist: Bar2 (last_modified: 2014-05-16)
Todo: Bang3 (last_modified: 2014-05-16)
Тоді, коли настає час візуалізації, завантаження Project
з бази даних в основному неминуче. Для початку вам потрібна точка. Однак, оскільки last_modified
це показник для всіх його дітей , саме це ви використовуєте як кеш-ключ, перш ніж намагатися завантажити дітей.
Поки в блогах використовуються окремі шаблони, я збираюся зібрати їх в один. Сподіваємось, побачення повної взаємодії в одному місці зробить це трохи зрозумілішим.
Отже, шаблон Джанго може виглядати приблизно так:
{% 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 %}
Скажімо, ми передаємо проект, який cache_key
досі існує в кеші. Оскільки ми поширюємо зміни на всі пов’язані об'єкти з батьків, факт, що цей конкретний ключ все ще існує, означає, що весь виведений вміст може бути витягнутий з кеша.
Якщо цей конкретний проект щойно був оновлений - наприклад, як це було Foo
зазначено вище - тоді він повинен буде надати своїх дітей, і лише тоді він виконуватиме запит для всіх тодолістів для цього проекту. Так само і для конкретного Todolist - якщо cache_key цього списку існує, то тодоси всередині нього не змінилися, і все це можна витягнути з кеша.
Також зауважте, як я не використовую todo.cache_key
цей шаблон. Це не варто, оскільки, як ви говорите в запитанні, body
вже витягнули з бази даних. Однак звернення до бази даних - не єдина причина, по якій ви можете щось кешувати. Наприклад, взяття необробленого тексту розмітки (наприклад, те, що ми вводимо у поля запитань / відповідей на StackExchange) та перетворення його в HTML може зайняти достатньо часу, щоб кешування результату було більш ефективним.
Якби це було так, внутрішня петля в шаблоні може виглядати приблизно так:
{% for todo in list.todos.all %}
{% cache 9999 todo todo.cache_key %}
<li>{{ todo.body|expensive_markup_parser }}</li>
{% endcache %}
{% endfor %}
Отже, щоб зібрати все разом, повернемося до моїх оригінальних даних у верхній частині цієї відповіді. Якщо припустити:
- Усі об'єкти були кешовані у первісному стані
Bang3
щойно оновлено
- Ми надаємо модифікований шаблон (у тому числі
expensive_markup_parser
)
Тоді ось як би все було завантажено:
Foo
витягується з бази даних
Foo.cache_key
(2014-05-16) не існує в кеші
Foo.todolists.all()
запитується: Bar1
і Bar2
отримується з бази даних
Bar1.cache_key
(2014-05-10) вже існує в кеші ; отримати та вивести його
Bar2.cache_key
(2014-05-16) не існує в кеші
Bar2.todos.all()
запитується: Bang3
і Bang4
отримується з бази даних
Bang3.cache_key
(2014-05-16) не існує в кеші
{{ Bang3.body|expensive_markup_parser }}
надається
Bang4.cache_key
(2014-04-01) вже існує в кеші ; отримати та вивести його
Економія з кеша в цьому крихітному прикладі:
- Уникає звернення до бази даних:
Bar1.todos.all()
expensive_markup_parser
уникали 3 рази: Bang1
, Bang2
іBang4
І звичайно, наступного разу, коли його буде переглянуто, Foo.cache_key
було б знайдено, тож єдиною витратою на надання є вилучення Foo
самостійно з бази даних та запит кеша.