2014-06-23 1 views
0

보고있는 동안 필드 값 목록을 변경하고 있지만 변경되지 않은 값을 컨텍스트로 전달하려고합니다. 여기의 경우는 알림을 볼 때 상태를보기로 변경해야하는 기본 알림 시스템입니다.Django : 컨텍스트에서 전달한 후 모델 변경

views.py는

class Notification(TemplateView): 

template_name='myapp/notification.html' 

def get_context_data(self, **kwargs): 
    user = self.request.user 
    user_unread = user.notification_set.filter(viewed=False) 
    user_read = user.notification_set.filter(viewed=True) 
    context = super(Notification, self).get_context_data(**kwargs) 
    context.update({'user_unread': user_unread, 'user_read': user_read}) 
    for msg in user_unread: 
     msg.viewed = True 
     msg.save() 
    return context 

그러나이 코드의 문제점, 나는 상황을 업데이트 한 후 모델에 새로운 값을 저장 한 비록 내가 읽기 및 읽지 않은 목록에 중복 값을 얻고 있다는 것입니다 템플릿에 전달됩니다.

템플릿하십시오 (!) 참고에

Unread: 
<ul> 
{% for msg in user_unread %} 
    <li> {{ msg }} </li> 
{% endfor %} 
</ul> 

Already read: 

<ul> 
{% for msg in user_read %} 
    <li> {{ msg }} </li> 
{% endfor %} 
</ul> 

, 나는 CBVs에 새로운 오전 내보기 위의 코드가 개선 될 수 있다면 만약 내가 몇 가지 포인터를 싶네요.

답변

1

이는 쿼리 세트의 게으른 특성 때문입니다. Queryset은 평가할 때까지 데이터베이스를 실제로 건드리지 않습니다. 일반적으로 반복 할 때 발생합니다. 따라서 코드에서보기의 user_unread을 반복하여 읽기 상태를 설정하면 쿼리 세트의 내용이 그 지점에서 고정됩니다. 그러나 템플릿을 찾을 때까지 user_read을 반복하지 않으므로 이후에 쿼리가 만들어지지 않으므로 이후에 모든 읽지 않은 알림을 업데이트해야합니다.

이 문제를 해결하려면 읽지 않은 쿼리를 업데이트하기 전에보기에서 읽기 쿼리 세트를 명시 적으로 평가해야합니다. 당신은 단순히에 list를 호출하여이 작업을 수행 할 수 있습니다 :

context.update({'user_unread': user_unread, 'user_read': list(user_read)}) 
for msg in user_unread: 
    ... 
1

당신은 개체를 업데이트하도록 설정 다른 중복 된 질의를 받고 시도 할 수 있습니다. 템플릿 컨텍스트에 대해 업데이트되지 않은 것을 사용하고 다른 템플릿 컨텍스트로만 업데이트하십시오.

처럼 :

def get_context_data(self, **kwargs): 
    user = self.request.user 
    user_unread = user.notification_set.filter(viewed=False) 

    #Do some operation on qs so that it gets evaluated, like 
    nitems = len(user_unread) 

    #get another queryset to update 
    user_unread_toupdate = user.notification_set.filter(viewed=False) 

    user_read = user.notification_set.filter(viewed=True) 
    context = super(Notification, self).get_context_data(**kwargs) 
    context.update({'user_unread': user_unread, 'user_read': user_read}) 

    #Use 2nd queryset 
    for msg in user_unread_toupdate: 
     msg.viewed = True 
     msg.save() 
    return context 

장고는 다르게 각각의 검색어에 대해 캐시 것입니다. 따라서 일단 평가되면 user_unread은 자체 복사본을 갖게됩니다.

비록 비슷한 쿼리 세트의 여러 사본이 매우 효율적이거나 효율적이지는 않지만, 레코드 수가 많으면 느려질 것입니다.

+0

아니요, 정확하게 같은 이유로 업데이트가 완료 될 때까지 쿼리 세트가 평가되지 않으므로 메시지는 항상 읽기 전용으로 표시됩니다. –

+0

@DanielRoseman, QS'len (user_unread)'를 평가하고 평가 한 결과를 얻은 후에 QS'len (user_unread)'를 평가했습니다. – Rohan

+0

아, 미안, 못 봤어. –

관련 문제