Django 继承和永久链接
我正在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
此问题的经典解决方案往往是将 ContentType 添加到存储该实例的子类类型的超类< /a>.这样您就可以依赖一致的 API,该 API 返回适当类型的相关子类对象。
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.
您可以使用 django-model-utils 中的 InheritanceManager 来避免添加内容类型字段。
然后,如果您在查询集上调用
.select_subclasses
,它将向下转换所有对象,例如: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.all()
返回FooPage
类型的所有对象,这些对象将混合 FooPage、FooBlog、FooGallery 的底层数据库表行。要获取正确的 URL,您应该获取 FooBlog 或 FooGallery 对象,例如,如果页面只是通过 FooPage 创建的页面对象,它可能会抛出 FooBlog.DoesNotExist 错误,因此要获取正确的 url,您可以执行类似的操作或者
,如果您不希望 FooPage 成为真正的表,则可以尝试使 FooPage 成为抽象类。
FooPage.objects.all()
returns all the objects of typeFooPage
, 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.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 thisalternatively you may try to make FooPage a abstractclass if you do not want FooPage to be a real table.