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

Django结合django-model-utils:如何同时继承两个模型?

解决Django同时继承TimeStampedModel和SoftDeletableModel的问题

嘿,这个场景我太熟悉了!其实django-model-utils里的这两个抽象模型完全可以同时继承,你之前尝试失败大概率是没踩对Django抽象模型多继承的正确姿势,或者忽略了一些细节。下面给你两种最优实现方案,亲测可用:

方案一:封装组合抽象基类(推荐)

因为TimeStampedModel和SoftDeletableModel都是抽象模型(abstract=True),Django原生支持这类模型的多继承。我们可以先把它们组合成一个自定义的抽象基类,之后所有业务模型都继承这个基类,既复用性强又代码整洁:

from django.db import models
from model_utils.models import TimeStampedModel, SoftDeletableModel

# 组合两个功能到一个抽象基类
class BaseModel(TimeStampedModel, SoftDeletableModel):
    class Meta:
        abstract = True

# 业务模型直接继承这个基类
class Product(BaseModel):
    name = models.CharField(max_length=200)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    # 其他业务字段...

这样你的Product模型就同时拥有了:

  • created/modified自动时间戳字段(来自TimeStampedModel)
  • is_removed/removed软删除字段,以及自动过滤已删除实例的管理器(来自SoftDeletableModel)

方案二:业务模型直接多继承

如果不想额外封装基类,也可以让业务模型直接同时继承两个模型,效果是一样的:

from django.db import models
from model_utils.models import TimeStampedModel, SoftDeletableModel

class Product(TimeStampedModel, SoftDeletableModel):
    name = models.CharField(max_length=200)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    # 其他业务字段...

    class Meta:
        verbose_name = "产品"
        verbose_name_plural = "产品列表"

为什么你之前尝试失败?可能的坑

  1. 忘记设置抽象模型的Meta类:如果你自己组合的时候,没有给自定义基类加上abstract = True,Django会把它当成普通模型生成数据表,就会出现字段重复或继承错误。
  2. 字段冲突误解:其实这两个模型的字段完全不重叠——TimeStampedModel只有created和modified,SoftDeletableModel是is_removed和removed,不存在字段重复问题。
  3. MRO顺序问题:如果有方法重名(这两个模型里没有),继承顺序会影响方法解析,但这里两个模型的save()和delete()方法各司其职,顺序不影响功能,放心用。

验证功能是否正常

  • 创建实例时,created和modified会自动填充当前时间
  • 调用instance.delete()时,不会真的删除数据,而是把is_removed设为True,removed设为删除时间
  • 查询Product.objects.all()时,会自动过滤掉is_removed=True的实例(如果需要查询已删除的,用Product.all_objects.all())

内容的提问来源于stack exchange,提问作者J. Hesters

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:49:34