Django 将页面对象转换为其页面派生对象

Django 将页面对象转换为其页面派生对象,django,wagtail,Django,Wagtail,我是个新手,但我不断遇到一些事情,我确信有比我现在做的更好的解决方案 假设我有一个叫做ProductPage的摇摆页面。假设此页面有一个字段,它是另一个名为related_product的ProductPage。当我尝试通过以下代码在模板或上下文中访问此页面时 self.related_product 它返回一个页面对象而不是ProductPage对象。因此,如果不通过以下方式将其转换为ProductPage对象,我就无法访问实际需要的字段: ProductPage.objects.get(p

我是个新手,但我不断遇到一些事情,我确信有比我现在做的更好的解决方案

假设我有一个叫做ProductPage的摇摆页面。假设此页面有一个字段,它是另一个名为related_product的ProductPage。当我尝试通过以下代码在模板或上下文中访问此页面时

self.related_product
它返回一个页面对象而不是ProductPage对象。因此,如果不通过以下方式将其转换为ProductPage对象,我就无法访问实际需要的字段:

ProductPage.objects.get(page_ptr_id=self.related_product.id)

必须有一种方法可以在不使用上述查询的情况下将其转换。

页面
实例转换为更具体的模型的标准方法是访问
特定的
属性:

product_page = some_page.specific  # returns a ProductPage instance
但是,这将在内部执行数据库查询,因此它不会比上面的代码更高效(只是更可读)。如果您有一个
Page
s的查询集,您可以通过在查询集上调用
specific()
稍微改进一下,这将对查询集中存在的每个不同页面类型执行一个额外的查询:

product_pages = product_index.get_children().specific()
但是,在您的情况下,有一个更好的解决方案:如果
相关的\u产品
字段仅用于链接到
产品页面
,而不是任何其他类型的页面,那么您应该通过将外键指向
产品页面
,而不是
页面
,在数据模型中指出这一点:

class ProductPage(Page):
    # ...
    related_product = models.ForeignKey('myapp.ProductPage', null=True, blank=True, on_delete=models.SET_NULL)

执行此操作时,访问
some\u page.related\u product
将始终为您提供
ProductPage
实例。作为一个额外的好处,Wagtail管理中的页面选择器弹出窗口将确保您只能选择ProductPages(如果您的所有ProductPages都位于页面树中的同一位置,则会直接将您带到那里)。

此处显示了如何在Wagtail中正确链接页面-。这些教程不是免费的,但是很便宜,注册可以随时取消。说到这里,我已经用了一年多他的教程了。