您可以采取几种方法来处理执行此类查询时获得的“混合模型”QuerySets。很大程度上取决于您的最终目标。
我经常使用的“简单而笨拙”的方法是使用实用函数来管理结果。例如,如果您计划在模板中处理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。但请注意,几乎所有此类解决方案都会受到性能限制。