在 Django 中使用继承过滤模型
Posted
技术标签:
【中文标题】在 Django 中使用继承过滤模型【英文标题】:Filtering models with inheritance in Django 【发布时间】:2010-11-15 15:38:04 【问题描述】:我有两个结构类似于以下的 Django 模型类:
类构建(models.Model): 项目 = models.CharField(max_length=100) ... 类自定义构建(构建): 自定义类型 = ... ...
我想从具有特定项目属性的数据库中选择所有构建和自定义构建(每个自定义构建与构建具有一对一的关系)。
我相信 Build.objects.filter(project="myproject") 会选择正确的对象,但其中许多会丢失由 CustomBuild 对象提供的附加数据(例如 custom_type)。另一方面,过滤 CustomBuild.objects 将排除那些不是 CustomBuilds 的对象。
我怎样才能做到这一点?谢谢。
【问题讨论】:
【参考方案1】:您可以采取几种方法来处理执行此类查询时获得的“混合模型”QuerySet
s。很大程度上取决于您的最终目标。
我经常使用的“简单而笨拙”的方法是使用实用函数来管理结果。例如,如果您计划在模板中处理Build.objects.filter(project="myproject")
的结果,您可以使用自定义模板标签或过滤器来采取特殊操作。假设在下面的代码中build_objects
包含您的 filter() 的结果:
% for build in build_objects %
% if build|is_custom_build %
<p>This is a custom build of custom type build.custom_build.custom_type !</p>
% endif %
<p>This is a custom build OR a standard build</p>
% endfor %
这里明显的问题是,如果您有许多子类,编写模板过滤器可能不切实际或变得乏味。但是,根据我的经验,我通常最多有六个子类,所以这并不总是一个问题。
您也可以像这样编写参数化过滤器:
% if build|is_of_buildtype:"custom_build" %
过滤器代码如下:
def is_of_buildtype_filter(value, arg):
if hasattr(value, arg): return True
else: return False
此过滤器仅检查参数是否作为build
对象上的属性(以value
传递)。参数字符串应该是您要检测的自动生成的OneToOneField
的名称,在本例中为custom_build
。
对于视图代码,类似的辅助函数可以以相同的方式工作,但更简单,因为您不需要编写自定义过滤器或标签。
这种方法在许多情况下都有效,但在更复杂的情况下可能不实用。不幸的是,当您对基类执行操作时,Django 无法原生地为您提供包含子类实例的QuerySet
(即真正包含“混合模型”的QuerySet
)。在无法使用辅助函数处理结果的情况下,您可能需要这样做。
我个人完全避免了这些情况,通常是通过重新思考我的模型设计。但如果这不可能,那么有很多有趣的解决方案尝试,比如Inheritance MixIn。还有几个关于这个主题的 Django sn-ps。但请注意,几乎所有此类解决方案都会受到性能限制。
【讨论】:
感谢您花时间撰写此评论。不过,我真的对如何在代码而不是模板中执行此操作更感兴趣。我希望我能接受这两个答案,因为我发现你的 hasattr 代码很有用,但我赞成你的答案。【参考方案2】:您可以使用 Build.objects.filter() 获取构建对象并在需要时访问子类:
qs = Build.objects.all()
build_obj = qs[4]
custom_build_obj = build_obj.custom_build
custom_build_obj.custom_type = ...
【讨论】:
以上是关于在 Django 中使用继承过滤模型的主要内容,如果未能解决你的问题,请参考以下文章