2009-10-06 4 views
13

UserProfile 객체에 JSON 객체가 포함 된 여러 TextField 열이 있습니다. 필자는 JSON을 파이썬 데이터 구조로 직렬화 및 비 직렬화하는 로직을 캡슐화하는 각 열에 대한 setter/getter 속성도 정의했습니다.Django 모델 객체에서 값 비싼 계산을 어떻게 메모합니까?

이 데이터의 특성상 단일 요청 내에서보기 및 템플릿 논리를 통해 여러 번 액세스 할 수 있습니다. deserialization 비용을 절약하기 위해, 나는 read시에 파이썬 데이터 구조를 메모하고, 속성에 대한 직접 작성시 무효화하거나 모델 객체에서 신호를 저장하고 싶습니다.

어디에서 어떻게 메모를 저장합니까? 특정 UserProfile이 쿼리에 의해 인스턴스화 된 방법을 이해하지 못하기 때문에 인스턴스 변수를 사용하는 것이 불안합니다. __init__을 사용하는 것이 안전합니까? 아니면 각 읽기시에 hasattr()을 통해 메모 속성의 존재를 확인해야합니까?

여기에 내 현재 구현의 예 :

class UserProfile(Model): 
    text_json = models.TextField(default=text_defaults) 

    @property 
    def text(self): 
     if not hasattr(self, "text_memo"): 
      self.text_memo = None 
     self.text_memo = self.text_memo or simplejson.loads(self.text_json) 
     return self.text_memo 
    @text.setter 
    def text(self, value=None): 
     self.text_memo = None 
     self.text_json = simplejson.dumps(value) 

답변

23

내장형 장고 장식재 django.utils.functional.memoize에 관심이있을 수 있습니다.

장고는 URL 해석과 같은 값 비싼 연산을 캐시하기 위해 이것을 사용합니다.

+0

잘 알고 있습니다. 감사. –

+16

클래스 메소드의 경우'django.utils.functional.cached_property'를 사용하는 것을 선호합니다. 클래스 메쏘드의 첫 번째 인수가'self'이므로 memoize는 객체를 버리고 난 후에도 객체에 대한 참조와 함수의 결과를 유지합니다. 가비지 컬렉터가 부실 객체를 정리하지 못하게하여 메모리 누수가 발생할 수 있습니다. 'cached_property'는 다니엘의 제안을 데코레이터로 바꾸어줍니다. – Arion

+0

아리온, 이것은 정확히 내가 뭘 찾고 있었는지 :-) – pstadler

16

을 일반적으로,이 같은 패턴을 사용 :

def get_expensive_operation(self): 
    if not hasattr(self, '_expensive_operation'): 
     self._expensive_operation = self.expensive_operation() 
    return self._expensive_operation 

는 그런 다음 데이터에 액세스 할 수 get_expensive_operation 방법을 사용합니다.

그러나 귀하의 경우에는 약간 잘못된 방향으로 접근하고 있다고 생각합니다. 모델이 데이터베이스에서 처음로드 될 때 비 직렬화를 수행하고 저장시에만 직렬화해야합니다. 그런 다음 매번 표준 Python 사전으로 속성에 액세스 할 수 있습니다. 이를 위해 사용자 정의 JSONField 유형을 정의하고 to_pythonget_db_prep_save을 재정의하는 models.TextField를 서브 클래 싱하여이 작업을 수행 할 수 있습니다.

실제로 누군가가 이미 완료했습니다 : here을 참조하십시오.

+0

당신은 전적으로 옳습니다. 우리는 이미 사전을 받아서 조작하고 설정자에게 다시 보내야한다는 것을 짜증나게했습니다. 사전을 제자리에서 조작하는 것이 훨씬 낫습니다. JSON 필드 구현은 흥미 롭습니다.하지만 어떻게 작동하는지 확실하지 않습니다. 한번로드시 deserialize 할 수 있으며, 조작 가능한 파이썬 객체를 제공 한 다음 저장시 다시 직렬화됩니까? –

+0

예, 정확하게. 그 사이에 일반 사전입니다. –

1

클래스 메서드의 경우 django.utils.functional.cached_property을 사용해야합니다.

클래스 메서드의 첫 번째 인수가 self이므로 memoize은 던져 버린 후에도 개체와 함수 결과에 대한 참조를 유지 관리합니다. 가비지 컬렉터가 부실 객체를 정리하지 못하게하여 메모리 누수가 발생할 수 있습니다. cached_property은 Daniel의 제안을 데코레이터로 바꿉니다.

+0

이것은 받아 들여진 응답이어야합니다. – mrts