You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中父模型ListView视图能否访问子模型字段?

问题:Django继承模型在ListView中能否访问子类字段?

我创建了productForArt和albomForArt模型,其中albomForArt继承自productForArt。基于generic.ListView创建视图并在模板中输出数据,请问能否在模板中访问albomForArt模型的numberOfPages字段?或者此时Django返回的是带有albomForArt属性的albomForArt对象吗?

模型代码

from django.db import models


class productForArt(models.Model):
    class Meta:
        verbose_name = u'товар'  # 商品
        verbose_name_plural = u'товары'  # 商品(复数)
    price = models.IntegerField(verbose_name="цена", default=0)  # 价格
    title = models.CharField(max_length=300, verbose_name="название товара", null=True)  # 商品名称
    description = models.CharField(max_length=1000, verbose_name="Описание товара", null=True)  # 商品描述
    type = models.ForeignKey('typeProductForArt', on_delete=models.PROTECT)
    def getType(self):
        return self.type
    def __str__(self):
        return str(self.title) + ' по цене' + str(self.price) + ' шт'  # 名称 + 价格 + 件

class albomForArt(productForArt):
    numberOfPages = models.IntegerField(default=10, verbose_name="количество станиц")  # 页数


class typeProductForArt(models.Model):
    title = models.CharField(max_length=200, default="none")
    def __str__(self):
        return self.title

视图代码

from django.views import View, generic
from .models import productForArt

class startPage(generic.ListView):
    model = productForArt
    template_name = "startPage.html"
    context_object_name = "productForArt_list"
    queryset = productForArt.objects.all()[:20]

模板代码

{% if productForArt_list %}
    <section class="productsStartpage">
        {% for productForArt in object_list %}
        <article class="productForArtStartpage">
            <h1>{{productForArt.title}}</h1>
            <p>{{productForArt.description}}</p>
        </article>
        {% endfor %}
    </section>
{% else %}
    <p>товара нету</p> <!-- 没有商品 -->
{% endif %}

回答

关于返回的对象

你当前的ListView查询productForArt.objects.all()会返回所有productForArt及其子类albomForArt的实例,但默认是以父类productForArt的形式返回。不过Django会自动为子类实例添加一个小写类名的关联属性(比如albomforart),通过这个属性可以访问子类的专属字段。

模板中访问numberOfPages的方法

直接写{{ productForArt.numberOfPages }}会报错(非albomForArt实例没有该字段),可以用以下几种方式处理:

1. 自定义模板标签判断类型

在app下创建templatetags/product_tags.py:

from django import template
from ..models import albomForArt

register = template.Library()

@register.filter
def is_albom(obj):
    return isinstance(obj, albomForArt)

模板中加载标签后使用:

{% load product_tags %}
{% for product in productForArt_list %}
    <article class="productForArtStartpage">
        <h1>{{ product.title }}</h1>
        <p>{{ product.description }}</p>
        {% if product|is_albom %}
            <p>页数:{{ product.albomforart.numberOfPages }}</p>
        {% endif %}
    </article>
{% endfor %}

2. 利用模板容错性处理

Django模板会忽略不存在的属性,结合default过滤器避免显示空值:

{% for product in productForArt_list %}
    <article class="productForArtStartpage">
        <h1>{{ product.title }}</h1>
        <p>{{ product.description }}</p>
        <p>页数:{{ product.albomforart.numberOfPages|default:"无" }}</p>
    </article>
{% endfor %}

3. 使用多态查询优化(推荐)

安装django-polymorphic库(pip install django-polymorphic),并将其加入INSTALLED_APPS,然后修改查询集:

# views.py
queryset = productForArt.objects.all().select_subclasses()[:20]

此时查询返回的是实际子类的实例,模板中可直接判断并访问:

{% load product_tags %}
{% for product in productForArt_list %}
    <article class="productForArtStartpage">
        <h1>{{ product.title }}</h1>
        <p>{{ product.description }}</p>
        {% if product|is_albom %}
            <p>页数:{{ product.numberOfPages }}</p>
        {% endif %}
    </article>
{% endfor %}

关键结论

  • Django返回的父类查询结果中,子类实例会携带对应的子类属性,可通过小写类名关联属性访问;
  • 必须先判断对象是否为子类实例,再访问专属字段,避免模板报错。

内容的提问来源于stack exchange,提问作者Камил Нарыгин

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 08:50:36