Django / 结合 DetailView FormMixin 和基于函数的视图

Django / combinig DetailView FormMixin and Function based views

我尝试用 django 制作一个 reddit 克隆。 问题是我不能结合 DetailView 和基于函数的视图。 我可以创建 post 和对特定 post 的评论,但无法进行嵌套评论。 我创建了逻辑但无法呈现它。 我应该如何呈现嵌套评论?我无法通过 get_context_data

获取数据

views.py

class EntryDetail(DetailView, FormMixin):
    template_name = 'post_detail.html'
    model = Post
    form_class = CommentForm

    def get_success_url(self):
        return reverse_lazy('post-detail', kwargs={'pk': self.object.pk})

    def get_context_data(self, **kwargs):
        context = super(EntryDetail, self).get_context_data(**kwargs)
        context['post_object'] = Post.objects.filter(pk=self.kwargs.get('pk'))
        context['comments'] = Post.objects.get(pk=self.kwargs.get('pk'))\
        .comments\
        .all()
        return context

    def post(self, request, *args, **kwargs):
        form = self.get_form()
        p_object = Post.objects.get(pk=self.kwargs.get('pk'))
        if form.is_valid():
            form.save(post=p_object.id)
            return redirect(reverse_lazy(
                            'post-detail', kwargs={'pk': p_object.pk}))


def add_sub_comment(request, comment_id):

    comment = Comment.objects.get(pk=comment_id)
    if request.POST:
        form = SubCommentForm(request.POST)
        if form.is_valid():
            form.save(comment_object=comment.id)
            return redirect('index')

    sub_comments = Comment.objects.filter(object_id=comment.id)
    ctx = {'sub_comments': sub_comments}
    return render(request, 'post_detail.html', ctx)

urls.py

urlpatterns = [
    url(r'^$', EntryView.as_view(), name='index'),
    url(r'^new_post/$', EntryCreate.as_view(), name='new-post'),
    url(r'^post_detail/(?P<pk>\d+)/$',
                         EntryDetail.as_view(), name='post-detail'),
    url(r'^sub_comments/(?P<comment_id>\d+)/$',
                         views.add_sub_comment, name='sub-comment'),
]

post_detail.html

{% for comment in comments %}
<div class="comment-per-style">
    {{ comment.entry_comment }}
    {% for subcomment in sub_comments %}
    <ul>
        <li>{{ subcomment.entry_comment }}</li>
    </ul>
    {% endfor %}
</div>
<form action="{% url 'sub-comment' comment.id %}" method="post">
    {% csrf_token %}
    <input id="entry_comment" type="text" name="entry_comment" maxlength="100" required />
    <input type="submit" value="OK">
</form>
{% endfor %}

forms.py

class SubCommentForm(forms.ModelForm):

    class Meta:
        model = Comment
        fields = ('entry_comment',)
        widgets = {
            'entry_comment': forms.TextInput(attrs={'class': 'form-input'}),
        }

    def save(self, comment_object):
        comment = Comment()
        comment.entry_comment = self.cleaned_data['entry_comment']
        comment.object_id = comment_object
        comment.content_type_id = 7
        comment.save()

    def __init__(self, *args, **kwargs):
        super(SubCommentForm, self).__init__(*args, **kwargs)
        # deleted form label
        self.fields['entry_comment'].label = ""

models.py

class Comment(models.Model):
    entry_comment = models.TextField(max_length=160)

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return self.entry_comment

class Post(models.Model):
    subject = models.CharField(max_length=20)
    entry = models.TextField(max_length=160)
    comments = GenericRelation(Comment)

    def get_absolute_url(self):
        return reverse('index')

    def __str__(self):
        return self.subject

你可以试试:

在模型中添加方法sub_comments

class Comment(models.Model):
    entry_comment = models.TextField(max_length=160)

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return self.entry_comment

    def sub_comments(self):
        ct = ContentType.objects.get_for_model(self)
        childs = Comment.objects.filter(content_type=ct, object_id=self.pk)
        return childs

    def descendants_comments(self):
        ct = ContentType.objects.get_for_model(self)
        childs = Comment.objects.filter(content_type=ct, object_id=self.pk)
        result = []
        for child in childs:
            result.append(child)
            result.append(child.descendants_comments())
        return result

并在模板中使用它:

        {{ comment.entry_comment }}
        {% for subcomment in comment.sub_comments %}
                       <!-- ^^^New^^^-->
        <ul>
            <li>{{ subcomment.entry_comment }}</li>
        </ul>
       {% endfor %}