이미로드 된 단일 객체의 스트레이트 덤프를 캐싱하려면 아무것도 얻거나 아무것도 얻지 못합니다. 그것은 그 예들이 묘사하는 것이 아닙니다. 그것들은 계층 구조를 설명하고 있습니다. 하위 계층에 대한 변경은 계층 구조에서 상위에있는 모든 것에 대한 업데이트를 유발해야합니다.
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
의 표시기 이므로 하위 항목 을로드하기 전에 캐시 키로 사용합니다.
블로그 게시물은 별도의 템플릿을 사용하지만 템플릿을 하나로 묶습니다. 한곳에서 완전한 상호 작용을 보는 것이 조금 더 명확 해지기를 바랍니다.
따라서 Django 템플릿은 다음과 같습니다.
{% 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에 대한 쿼리를 실행합니다. 특정 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
하고 캐시를 쿼리하는 데 드는 유일한 비용 입니다.