如何在Django中使用通用外键嵌套模型?

时间:2015-11-17 11:03:09

标签: python django nested

我正在做我的第一个Django项目,这不是一个教程,我认为尝试建立一个类似reddit的网站是一个很好的学习经历。所以我有一个Link模型和一个Comment模型。 Comment模型有一个GenericForeignKey,因为它可以引用一个Link或另一个Comment。我希望这些评论能够在彼此之间筑巢,但我不知道如何。有人有什么想法吗?

This is the project,这是models.py:

from django.db import models
from django.utils import timezone
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

# Create your models here.
class Link(models.Model):
    title = models.CharField(max_length=140)
    url = models.URLField(unique=True)
    posted = models.DateTimeField(default=timezone.now)
    upvotes = models.IntegerField(default=0)
    downvotes = models.IntegerField(default=0)

    def score(self):
        return self.upvotes - self.downvotes

    def __str__(self):
        return self.title

class Comment(models.Model):
    text = models.TextField()
    posted = models.DateTimeField(default=timezone.now)
    upvotes = models.IntegerField(default=0)
    downvotes = models.IntegerField(default=0)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def score(self):
        return self.upvotes - self.downvotes

编辑:我写了this test并且它通过,这让我相信评论实际上可以嵌套。那么,问题是如何让它们在视图中嵌套?我的观点文件如下:

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType

from .models import Link, Comment
from .forms import LinkForm, CommentForm

# Create your views here.
def links(request):
    links = Link.objects.all().order_by('-posted')
    if request.method == 'POST':
        if request.user.is_authenticated():
            form = LinkForm(data=request.POST,auto_id=True)
            if form.is_valid():
                form.full_clean()
                form.save()
                return HttpResponseRedirect('/')
        else:
            return HttpResponseRedirect('/accounts/login/?next=/')
    else:
        form = LinkForm(auto_id=True)
    return render(request, 'posts/links.html', {'links': links, 'form': form})

def comments(request, link_id):
    link = get_object_or_404(Link, pk=link_id)
    comments = Comment.objects.filter(
        object_id = link.id,
        content_type=ContentType.objects.get_for_model(link)
    ).order_by('-posted')
    if request.method == 'POST':
        if request.user.is_authenticated():
            form = CommentForm(data=request.POST,auto_id=True)
            if form.is_valid():
                form.full_clean()
                form.save()
                return reverse('comments', kwargs={'link_id':link.id})
        else:
            return HttpResponseRedirect('/accounts/login/?next=/{0}/'.format(link.id))
    else:
        form = CommentForm(auto_id=True)
        return render(request, 'posts/comments.html', {'comments': comments, 'link': link, 'form': form})

1 个答案:

答案 0 :(得分:1)

我使用django-mptt来解决这个问题。

您只需为评论本身创建一个外键,然后将其余作业保留为mptt

你必须做这样的事情:

from mptt.models import TreeForeignKey, MPTTModel

class Comment(MPTTModel):
    ....
    ....
    parent = TreeForeignKey('self', related_name='children',
                            blank=True, null=True, db_index=True)

阅读文档@ django-mptt