2011-04-25 2 views
0

변경된 모델 필드에 액세스하여 Django 1.3 앱에서 관계를 트래핑하는 문제가 발생합니다. 데이터베이스에 커밋 된 변경 사항은 메모리 내 개체에 반영되지 않습니다. 나는 사용자 지정 프로필에 연결, 인증 미들웨어에서 사용자() 객체를 사용하고 있습니다() 객체 :왜 관계를 탐색 할 때 Django 모델 필드가 동기화되지 않습니까?

$ python manage.py shell 
>>> from django.contrib.auth.models import User 
>>> from myproject.myapp.models import Profile 
>>> 
>>> user = User.objects.get(pk=1) 
>>> profile = user.profile 
>>> user.email 
u'[email protected]'     # OK. 
>>> profile.user.email 
u'[email protected]'     # OK. 
>>> 
>>> user.email = '[email protected]' # 1) Changes email address. 
>>> user.save()      # 2) Commits to database. 
>>> user.email 
'[email protected]'     # 3) Changes reflected in user.email. Good. 
>>> profile.user.email 
u'[email protected]'     # 4) Wrong. This is the old incorrect email. 
>>> user.profile.user.email 
u'[email protected]'     # 5) Also wrong. 
>>> 
>>> profile = Profile.objects.get(user=user) 
>>> profile.user.email 
u'[email protected]'     # 6) If we re-query the DB, things are OK. 
: 사용자()에 대한 email 필드를 액세스 할 때

User() <---one-to-one---> Profile() 

문제가 온다

4 단계와 5 단계에서 상황이 동기화되지 않는 이유는 무엇입니까? 나는 # 5에 당황 스럽다. 저장된 사용자 객체에서 프로파일로 돌아가서 같은 저장된 사용자 객체로 돌아 간다.

분명히 어떤 종류의 캐싱이 진행되고 있지만 로직/알고리즘에 대한 확신이 없습니다. 누구나 무슨 일이 일어나고 있는지, 그리고 코드에서이 문제에 접근하는 가장 좋은 방법에 대한 아이디어가 있습니까? 제공 할 수있는 통찰력에 감사드립니다! :)

답변

2

관련 개체를 투명하게 조회하는 설명자는 모델 인스턴스의 _<fieldname>_cache에있는 관련된 개체의 캐시 된 버전을 검사하여 처음 검색 할 때 캐싱합니다.

Django의 ORM은 신원 맵을 사용하지 않으므로 하나의 Model 인스턴스에 대한 변경 사항은 기존 참조가 유지되는 다른 인스턴스에 자동으로 반영되지 않습니다.

+0

아, 재미 있습니다. 캐시되지 않은 버전을 사용하도록 강제 할 수 있습니까? 또는 새로운 QuerySet (예 : # 6)에서 가져와야합니까? –

+0

같은 질문이 있습니다 ... 재 쿼리 할 수있을만큼 간단하지만 refresh() 메서드가 있으면 좋은 것일 수도 있습니다. – acjay

+0

동의 한 메서드는 편리하지만 쉽게 다시 쿼리 할 수 ​​있습니다. [FYI, 여기에 해당 기능 요청이 있습니다.] (https://code.djangoproject.com/ticket/901) –

1

profile.user이 아니고user입니다. Django의 ORM이 이전에 데이터베이스에서 가져온 모델의 또 다른 캐시 된 사본입니다. 당신이 절대적으로 최신 값을 가져야한다면, 매번 재 쿼리해야합니다.

관련 문제