2

我正在 django 中创建一个简单的 CMS,其中包含多个“模块”(每个模块都作为一个 django 应用程序)。我设置了以下模型:

class FooObject(models.Model):
    id = models.SlugField(primary_key=True)
    name = models.CharField(max_length=255)
    creator = models.ForeignKey(auth.models.User, editable=False, related_name="createdby")

class FooPage(FooObject):
    content = models.TextField(blank=True, null=True)

    @models.permalink
    def get_absolute_url(self):
        return ('page', (), {'page_id':self.id}

class FooSubitem(FooObject):
    parent = models.ForeignKey(FooPage, related_name='subitems')

在每个模块中,我创建了一个 FooPage 的子类,以及至少一个 FooSubitem 的子类,例如

# in FooBlog.models
class FooBlog(FooPage):
    owner = models.ForeignKey(auth.models.User, editable=False)

    @models.permalink
    def get_absolute_url(self):
        return ('blog', (), {'blog_id':self.id})

class FooPost(FooSubitem):
    post_time = models.DateTimeField(auto_now_add=True)

# in FooGallery.models
class FooGallery(FooPage):
    location = models.CharField(max_length=255)

    @models.permalink
    def get_absolute_url(self):
        return ('gallery', (), {'gallery_id':self.id})

class FooImage(FooSubitem):
    image_file = models.ImageField(upload_to='foogallery')

这些是简化,但应该让您对我正在尝试做的事情有一个很好的了解。在 FooPost 和 FooImage 的管理员中,我将父选择列表限制为它们相应的父页面。

当我尝试在模板中使用这些时,我的问题就出现了。在每个视图中,我都有以下内容:

page_list = FooPage.objects.all()

它返回所有 FooPages 的列表,包括 FooBlog 和 FooGallery 类型。但是,当我遍历此列表时:

{% for page in page_list %}{{ page.get_absolute_url }}{% endfor %}

它返回 'page' url 模式,而不是 'blog' 或 'gallery' url 模式。

当我想稍后添加 FooCalendar 模块时,如何在不重写代码的情况下完成这项工作?我想确保这适用于任何可能的模块。

谢谢,

  • 莱克索
4

3 回答 3

2

这个问题的经典解决方案往往是将 ContentType 添加到存储该实例的子类类型的超类中。通过这种方式,您可以依赖返回适当类型的相关子类对象的一致 API。

于 2010-07-06T05:52:07.967 回答
1

您可以使用django-model-utils中的 InheritanceManager 避免添加内容类型字段。

然后,如果您调用.select_subclasses查询集,它将向下转换所有对象,例如:

FooPage.objects.select_subclasses().all()
于 2013-01-10T22:16:38.443 回答
0

FooPage.objects.all()返回所有类型的对象FooPage,这些对象将是 FooPage、FooBlog、FooGallery 的底层 db 表行的混合。要获取正确的 URL,您应该获取 FooBlog 或 FooGallery 对象,例如

page.fooblog.get_absolute_url()

FooBlog.DoesNotExist如果页面只是一个页面对象,即通过 FooPage 创建的,它可能会抛出错误,所以要获得正确的 url,你可以做这样的事情

   urls = []
   for page in FooPage.objects.all():
        try:
            page = page.fooblog
        except FooBlog.DoesNotExist:
            pass

            urls.append(page.get_absolute_url())

或者,如果您不希望 FooPage 成为真正的表,您可以尝试将 FooPage 设为抽象类。

于 2010-07-05T05:05:48.057 回答