Django 继承和永久链接

发布于 2024-09-08 08:01:24 字数 1787 浏览 6 评论 0原文

我正在 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()

它返回 FooBlog 和 FooGallery 类型的所有 FooPage 的列表。但是,当我迭代此列表时:

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

它返回“页面”url 模式,而不是“博客”或“画廊”url 模式。

当我稍后想添加 FooCalendar 模块时,如何才能完成这项工作而无需重写代码?我想确保这适用于任何可能的模块。

谢谢,

  • 莱克索

I'm creating a simple CMS in django, with multiple "modules" (each as a django app). I've set up the following models:

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')

In each of the modules, I create a subclass of FooPage, and at least one subclass of FooSubitem, e.g.

# 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)

and

# 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')

These are simplifications, but should give you a good idea of what I'm trying to do. In the admins for FooPost and FooImage, I restrict the parent selection list to their corresponding parent pages.

My problem arises when I try to use these in a template. In each view, I have the following:

page_list = FooPage.objects.all()

which returns a list of all FooPages, of both FooBlog and FooGallery types. However, when I iterate through this list:

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

it returns the 'page' url pattern, not the 'blog' or 'gallery' url pattern.

How do I make this work without having to rewrite the code when I want to add a FooCalendar module later on? I want to make sure this works with any possible module.

Thanks,

  • Lexo

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

总以为 2024-09-15 08:01:24

The classic solution to this problem tends to be adding a ContentType to the superclass which stores the type of subclass for that instance. This way you can rely on a consistent API that returns the related subclass object of the appropriate type.

鹤舞 2024-09-15 08:01:24

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

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

FooPage.objects.select_subclasses().all()

You can avoid adding a content type field by using the InheritanceManager from django-model-utils.

Then, if you call .select_subclasses on a queryset, it will downcast all of the objects, for example:

FooPage.objects.select_subclasses().all()
仅冇旳回忆 2024-09-15 08:01:24

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

page.fooblog.get_absolute_url()

如果页面只是通过 FooPage 创建的页面对象,它可能会抛出 FooBlog.DoesNotExist 错误,因此要获取正确的 url,您可以执行类似的操作或者

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

            urls.append(page.get_absolute_url())

,如果您不希望 FooPage 成为真正的表,则可以尝试使 FooPage 成为抽象类。

FooPage.objects.all() returns all the objects of type FooPage, these objects will be mix of underlying db table rows for FooPage, FooBlog, FooGallery. To get the correct URL you should get the FooBlog or FooGallery object e.g.

page.fooblog.get_absolute_url()

it may throw FooBlog.DoesNotExist error if page is simply a page object i.e created via FooPage, so to get correct urls you may do something like this

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

            urls.append(page.get_absolute_url())

alternatively you may try to make FooPage a abstractclass if you do not want FooPage to be a real table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文