2010-05-28 2 views
2

본질적으로 대화 시스템을 사용하는 앱이 있습니다 (reddit과 비슷합니다). 게시물이 여러 개의 응답을 가질 수 django의 다중 스레드 대화 (Reddit과 같은)

및 응답 및 증식이 있고, 응답에 대한 응답은

는이 같은 모델을했습니다 (등) 복수 응답 할 수 있습니다 :

class Discussion(models.Model): 
    message = models.TextField() 
    replies = models.ManyToManyField('self') 

하고 뷰 :

discussions = Discussions.objects.all() 

및 템플릿은 다음과 같습니다

{% for discussion in discussions %} 
    {{ discussion.message }} 
{% endfor %} 

이렇게 모든 답글을 출력 할 수있는 시스템을 만드는 방법은 무엇입니까?

discussion 
    reply 
     reply 
    reply 
     reply 
      reply 
       reply 

모든 답글이 나열되어 있는지 확인하는 데 필요한만큼 내려갑니다.

답변

4

회신이 여러 게시물에 대한 답글이 될 수있는 경우가 아니면 ManyToManyField은 원하는 것이 아닙니다.

class Discussion(models.Model): 
    message = models.TextField() 
    reply_to = models.ForeignKey('self', related_name='replies', 
     null=True, blank=True) 

그럼 당신은 Discussion.replies와 토론의 답변을 얻을 수 있습니다 : 당신은 단지 ForeignKey가 필요합니다.

불행히도 Django의 템플릿 언어에서 재귀를 수행 할 방법이 없으므로 1) 재귀 함수를 실행하여 응답의 "병합 된"목록을 가져온 다음 문맥에 넣거나 2)

_DiscussionTemplate = Template(""" 
<li>{{ discussion.message }}{% if replies %} 
    <ul> 
     {% for reply in replies %} 
     {{ reply }} 
     {% endfor %} 
    </ul> 
{% endif %}</li> 
""".strip()) 

class Discussion(models.Model): 
    message = models.TextField() 
    reply_to = models.ForeignKey('self', related_name='replies', 
     null=True, blank=True) 

    @property 
    def html(self): 
     return _DiscussionTemplate.render(Context({ 
      'discussion': self, 
      'replies': [reply.html() for reply in self.replies.all()] 
     })) 

그런 다음 최상위 템플릿에, 당신은 단지 필요 :

<ul> 
    {% for d in discussions %} 
    {{ d.html }} 
    {% endfor %} 
</ul> 

CSS를 적용처럼 호출 할 수있는 기능은 반복적으로 그 일을 보일 것이다 각 레벨을 생성하는 템플릿을 사용 멋지게 보이도록 원하는대로.

편집 : 루트 토론은 Discussion.objects.filter(reply_to=None)입니다. 모든 코드 (_DiscussionTemplate 포함)는 models.py에 있습니다. 이렇게하면 모듈이로드 될 때 _DiscussionTemplate이 한 번 초기화됩니다.

EDIT 2 : HTML을 템플릿 파일에 넣는 것은 매우 간단합니다.

_DiscussionTemplate = loader.get_template("discussiontemplate.html") 

그런 다음 discussiontemplate.html를 만들 :에 _DiscussionTemplate를 설정하는 뷰 코드 변경 필요에 따라

<li>{{ discussion.message }}{% if replies %} 
    <ul> 
     {% for reply in replies %} 
     {{ reply }} 
     {% endfor %} 
    </ul> 
{% endif %}</li> 

는 템플릿 파일의 경로를 설정합니다.

+0

_DiscussionTemplate은 어디로 이동합니까? 그것은 내 모델에 있습니까? 템플릿을 가져와야합니까? – dotty

+0

symmetrical = False 오류가 발생하여 제거 했으므로 여전히 작동합니까? – dotty

+0

루트 토론이 무엇인지 어떻게 알 수 있습니까? – dotty

1

체크 아웃 django-threadedcomments을 확인하십시오.

또한 부모 - 답장 관계는 ManyToMany - 부모의 자식 OneToMany이 아니기 때문에 주석 (기존의 스레드 된 주석 모델에서는 어쨌든)은 하나만 다른 주석 .

+0

그 링크는 내 머리 위로입니다. 다른 솔루션? – dotty

1

첫 번째 단계는 모델을 수정하는 것입니다. 내려다 보지 말고보세요.

class Discussion(models.Model): 
    message = models.TextField() 
    parent = models.ForeignKey(Discussion, null=True, blank=True) 

    def get_children(self): 
     return Discussion.objects.filter(parent=self) 

부모가없는 경우 루트 스레드입니다. 그럴 때, 그것은 답입니다.

디스플레이 로직을 약간 변경해야합니다. 모든 주석을 반복하는 대신 최상위 수준의 게시물을 반복합니다. 당신이 가진 것 주 템플릿에서

{{ comment.message }} 
{% for comment in comment.get_children %} 
    {% include comment.html %} 
{% endfor %} 

을 :

{% for comment in base_comments %} 
    {% include 'comment.html' %} 
{% endfor %} 

을 그리고 당신의보기에서, 당신의 상황에 'base_comments':Discussion.objects.filter(parent=None)를 추가하려면 comment.html 파일은 다음과 같이 나타납니다.

물론 형식을 지정하고 회신 프로세스를 처리해야하는 UI 요소가 있지만 여기까지 남겨 두겠습니다.

그리고이 모든 것을 매우 쉽게 아웃소싱 할 수 있다는 것을 잊지 마십시오. Disqus를 매우 효과적으로 사용합니다.