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

在Django中调用父类Event时如何使用子类及孙类的__str__方法?

解决Django模型继承中__str__递归错误的方案

问题原因分析

你原本通过InheritanceManager查询数据库获取子类实例并调用其__str__,但遇到孙类时会触发无限递归:

  • 当Event.__str__查询数据库拿到孙类实例后,若孙类未重写__str__,会调用父类(如FestivalEdition)的__str__
  • 若父类的__str__间接触发Event.__str__,就会形成循环调用,最终抛出RecursionError

另外你的FestivalEdition.__str__存在两处错误:

  • self.festival_name未定义,应改为self.father_festival.name(关联Festival的name字段)
  • self.year未定义,需在FestivalEdition中添加对应字段

修复方案

无需重复查询数据库,直接利用实例的真实类调用对应__str__,彻底避免递归:

1. 修正后的完整模型代码

from django.db import models
from datetime import date
from model_utils.managers import InheritanceManager  # 需先安装django-model-utils

class Event(models.Model):
    beginning = models.DateTimeField(null=False, blank=True, default=date.today)
    end = models.DateTimeField(null=False, blank=True, default=date.today)
    
    objects2 = InheritanceManager()

    def __str__(self) -> str:
        # 获取实例的真实类(而非当前声明的Event类)
        actual_class = self.__class__
        # 若真实类不是Event本身,直接调用对应类的__str__方法
        if actual_class != Event:
            return actual_class.__str__(self)
        # 纯Event实例的默认显示
        return f"Event object ({self.pk})"

class Festival(models.Model):
    name = models.CharField(max_length=100, blank=True)
    def __str__(self) -> str:
        return self.name or "Unnamed Festival"

class FestivalEdition(Event):
    type = "festival_edition"
    father_festival = models.ForeignKey(Festival, on_delete=models.CASCADE, related_name="edition")
    year = models.IntegerField()  # 添加缺失的year字段
    def __str__(self) -> str:
        # 修正字段引用
        return f"{self.father_festival.name} {self.year}"

# 示例孙类(即使不重写__str__也不会触发递归)
class SpecialFestivalEdition(FestivalEdition):
    special_note = models.CharField(max_length=200, blank=True)

2. 关键修复点

  • 通过self.__class__直接获取实例的真实类型,避免重复查询数据库,提升性能
  • 调用actual_class.__str__(self)而非self.__str__(),绕开方法解析顺序中可能触发的父类__str__调用,彻底阻断递归路径
  • 纯Event实例返回默认标识,保证基础场景的显示正常

3. 依赖安装

确保已安装django-model-utils库:

pip install django-model-utils

修改后,无论子类还是孙类实例,在以Event类型被调用时,都会正确显示对应子类的__str__内容,且不会触发递归错误。

内容的提问来源于stack exchange,提问作者Dhrions

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:47:34