帮助理解Django中的泛型关系(以及在Admin中的用法)

时间:2010-04-02 16:45:30

标签: django generic-relations

我正在为我公司的网站建立一个CMS(我已经看过现有的Django解决方案,想要更简单/更简单的东西,特别是处理我们的情况。另外,我想学习这些东西更好)。我无法绕过通用关系。

我有一个Page模型,一个SoftwareModule模型,以及一些定义我们网站上内容的模型,每个模型都定义了get_absolute_url()。我希望我的用户能够为任何Page实例分配任何类型的对象列表,包括其他页面实例。此列表将成为Page实例的子菜单。

我尝试了以下内容:

class Page(models.Model):
    body = models.TextField()
    links = generic.GenericRelation("LinkedItem")

    @models.permalink
    def get_absolute_url(self):
        # returns the right URL

class LinkedItem(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    title = models.CharField(max_length=100)

    def __unicode__(self):
        return self.title

class SoftwareModule(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()

    def __unicode__(self):
        return self.name

    @models.permalink
    def get_absolute_url(self):
        # returns the right URL

这让我与API有page_instance.links.all()的通用关系。我们正在路上。我不确定如何实现,是在页面实例的更改表单上,如何创建该页面与数据库中任何其他现存对象之间的关系。我想要的最终结果:在模板中呈现以下内容:

<ul>
{% for link in page.links.all %}
    <li><a href='{{ link.content_object.get_absolute_url() }}'>{{ link.title }}</a></li>
{% endfor%}
</ul>

显然,有一些我不知道或误解的东西,但我觉得我正在走进那个我不知道我不知道的地方。我错过了什么?

3 个答案:

答案 0 :(得分:1)

LinkedItem如何与Page相关联? GenericRelation用于反向关系,但现在它没有任何关系,所以没有任何东西可以匹配。我认为这正是您在模型设计中所寻求的:

class Page(models.Model):
    body = models.TextField()
    # Moved generic relation to below

class LinkedItem(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    # LinkedItems now relate to a Page model, and we're establishing the relationship
    # by specifying 'links' to keep the syntax you're looking for
    page = models.ForeignKey(Page, related_name='links')

    title = models.CharField(max_length=100)

另外,此模型设置允许一个LinkedItemPage相关联。如果您想重新使用链接项,可以将其设为M2M:

class Page(models.Model):
    body = models.TextField()
    links = models.ManyToManyField(LinkedItem)

class LinkedItem(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    title = models.CharField(max_length=100)

在这两个实例中,page.links.all()将是所有链接的项目。

此外,模板语法中不使用括号。

答案 1 :(得分:0)

在使用page.links.all

之前,我没有直接看过模板访问管理器

根据我的理解,您需要将链接作为视图中的列表拉回来,并将其作为变量传递给模板。此外,您需要提前解决任何外键,您可以使用select_related。

def some_view(request,*args,**kwargs):

  ...
  page_links = page_instace.links.select_related().all()
  ...

  return render_to_response(
                'the_template.html',
                #extra_context to pass to the template as var_name:value
                {
                    "page_links":page_links,
                },
                # needed if you need access to session variables like user info
                context_instance=RequestContext(request)
            )

然后在模板中......

<ul>
{% for link in page_links %}
    <li><a href='{{ link.content_object.get_absolute_url() }}'>{{ link.title }}</a></li>
{% endfor%}
</ul>

我已经提供了更多链接,但堆栈不会让我。

答案 2 :(得分:0)

您为什么要在link.content_object列表中访问page.link.all()?在此列表中,link.content_object将始终与page相同。

我认为我不了解您在此处尝试做什么,但现在代码应生成一个包含link.title文本的当前页面的链接列表。

您能解释一下您使用LinkedItem尝试做什么吗?