Django Web Framework/Django 일반

django template cache 사용방법 (MPTT 적용)

bluebamus 2023. 3. 17.

사전 작업

settings.py 설정

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
        "KEY_PREFIX": "devspoon",
    }
}

# Cache time to live is 15 minutes.
CACHE_TTL = 60 * 15
SESSION_ENGINE = "django.contrib.sessions.backends.cache"  # use only cache
SESSION_CACHE_ALIAS = "default"

 

Template에 cache 선언

{% load cache %}
.
.
# 원하는 코드 구간
# template_main_menu_pc 는 키 값이 됨
{% cache 604800 template_main_menu_pc %}
.
# 이 구간이 캐시가 됨
.
{% endcache %}

* MTPP의 경우 아래 코드에서 지속적으로 쿼리가 발생함

   - 코드 분석 결과 유무를 확인하는 과정이기에 캐시로 구현하기 복잡할 것으로 예상됨

   - 최적화, 고성능을 위해서는 MTPP 패키지를 쓰는건 옳지 않다는 것을 알고 있기에 template, templatetag에서 캐시를 통해 9회 이상의 캐시를 3회로 낮춘것으로 만족하기로 함

   - 대처안 : 단계형으로 구분 가능한 딕셔너리를 전송 및 캐싱하고, javascript로 구현하는게 좋다.

* 이전에 모델에서 cached_property로 구현한 사례를 본적이 있으나 현재 다시 찾지를 못해 적용을 못해봄 

{% if not node.get_next_sibling %}

 

Templatetags에 적용

from django import template
from django.conf import settings
from django.core.cache import cache
from django.core.cache.backends.base import DEFAULT_TIMEOUT

from home.models.default import MainMenu, SiteInfo

CACHE_TTL = getattr(settings, "CACHE_TTL", DEFAULT_TIMEOUT)

@register.simple_tag
def main_menu_tag():
    if "main_menu" in cache:
        main_menu = cache.get("main_menu") # 캐시 가져오기
    else:
        main_menu = MainMenu.objects.all()
        cache.set("main_menu", main_menu, timeout=CACHE_TTL) # 캐시 저장
    return main_menu

 

Admin에 적용

- menu의 생성, 업데이트, 삭제는 모두 admin에서만 발생한다. 

- admin에서 어떤 작업을 하던 캐시를 모두 날려주는 작업을 오버라이딩 하고 캐시만 날려주는 메뉴도 구현하기로 한다.

* 작업을 하면서 알게 된 것으로 리스트 페이지에서 모든 작업은 하나 이상의 아이템이 선택 되어 있는 상태여야 트리거가 동작한다.

class MainMenuAdmin(DraggableMPTTAdmin):
    actions = [
        "delete_all_of_main_cache",
        "delete_selected_items",
    ]

    # 리팩토링으로 캐시 클린을 정의함
    def delete_menu_cache(self):
        cache.delete("main_menu")
        key = make_template_fragment_key("template_main_menu_pc")
        cache.delete(key)

    # 기존 delete_selected 메뉴 삭제 (리스트 페이지)
    def get_actions(self, request):
        actions = super(MainMenuAdmin, self).get_actions(request)
        del actions["delete_selected"]
        return actions

    # delete_selected 메뉴 대체
    def delete_selected_items(self, request, queryset):
        for obj in queryset:
            self.delete_menu_cache()
            obj.delete()

    # 캐시만 삭제, 꼭 하나의 아이템이 선택 되어야 트리거가 동작한다
    def delete_all_of_main_cache(self, request, queryset):
        self.delete_menu_cache()

    # 생성, 업데이트 오버라이딩
    def save_model(self, request, obj, form, change):
        self.delete_menu_cache()
        super().save_model(request, obj, form, change)

    # 삭제 오버라이딩 (상세 페이지에서 삭제)
    def delete_model(self, request, obj):
        self.delete_menu_cache()
        super().delete_model(request, obj)

 

* 상위 코드는 현재 개발중인 프로젝트에 확인할 수 있다.

   - 소스가 많은 편이니 전체 찾기에서 함수명을 이용하면 된다.

https://github.com/devspoon/devspoon-portfolio-blog

 

GitHub - devspoon/devspoon-portfolio-blog

Contribute to devspoon/devspoon-portfolio-blog development by creating an account on GitHub.

github.com

 

* chatGPT로 오버라이딩 관련 질문을 해서 참고를 했는데 save 관련 코드는 쓸만했으나 delete 관련은 설명이 부족했었다. 하지만 반복된 구체적 질문을 하게 되면 원하는 답을 유도할 수 있을것 같았다. (stackoverflow에서 그냥 검색해서 해결함)

 

reference 

https://runebook.dev/ko/docs/django/topics/cache?page=3 

 

Django - 뷰당 캐시 캐싱 프레임워크를 사용하는 보다 세분화된 방법은 개별 보기의 출력을 사용하

Documentation Contributors History

runebook.dev

https://dingrr.com/blog/post/django-seo-%EB%8D%94-%EB%B9%A0%EB%A5%B4%EA%B2%8C-cache%EC%99%80-%EC%95%95%EC%B6%95

 

[Django SEO] 더 빠르게! - Cache와 압축 | 블로그 | 딩그르르

[Django SEO] 더 빠르게! - Cache와 압축

dingrr.com

https://books.agiliq.com/projects/django-admin-cookbook/en/latest/remove_delete_selected.html

 

3. How to remove the delete selected action in Django admin? — Django Admin Cookbook 2.0 documentation

3. How to remove the delete selected action in Django admin? By default Django adds a Delete Selected action to the listview page. You have been asked to remove the action from the Hero admin. The method ModelAdmin.get_actions returns the actions shown. By

books.agiliq.com

https://books.agiliq.com/projects/django-admin-cookbook/en/latest/override_save.html

 

3. How to override save behaviour for Django admin? — Django Admin Cookbook 2.0 documentation

3. How to override save behaviour for Django admin? ModelAdmin has a save_model method, which is used for creating and updating model objects. By overriding this, you can customize the save behaviour for admin. The Hero model has the following field.: adde

books.agiliq.com

https://stackoverflow.com/questions/15196313/django-admin-override-delete-method

 

Django admin: override delete method

I have admin.py as follows: class profilesAdmin(admin.ModelAdmin): list_display = ["type","username","domain_name"] Now i want to perform some action before deleting the object: class

stackoverflow.com

 

댓글