Django,multi-table 继承有那么糟糕吗?
Django, multi-table inheritance is that bad?
这并不是 django 特有的。
一罐模型
Place (with location, name, and other common attributes)
- Restaurant (menu..)
- ConcertHall (hall size..)
- 在两个单独的 table 中,让每个包含他们需要的所有字段。 (在django的世界里,这叫做抽象继承)
- 在三个 table 中,其中一个包含公共字段,另外两个有自己的独特字段。 (django 中的多table 继承)
Two scoops of Django 1.8 书的作者强烈建议不要使用多重 table 继承。
假设您想根据位置查询地点并对结果进行分页(不必是位置,可以是我们要过滤的任何其他常见属性)
我可以看到如何使用 Multi-table 继承来实现它。
select place.id from place LEFT OUTER JOIN "restaurant" on (
restuarant.id=place.id) LEFT OUTER JOIN "concerthall" on (
concerthall.id=place.id) where ... order by distance
用抽象继承来做可行吗?
根据Django documentation: Model inheritance:
The only decision you have to make is whether you want the parent models to be models in their own right (with their own database tables), or if the parents are just holders of common information that will only be visible through the child models.
我认为这两种可能性都只是工具,同样是好的工具,它们是否合适取决于您的用例。当然,这两种方法都有特定的事情需要考虑,而且从概念上讲,有时多重 table 继承可能更难以理解,但除此之外,这个话题变得自以为是。
如果两个模型都需要一个查询集,那么考虑多 table 继承而不是抽象模型是合乎逻辑的,因为否则您将需要将两个查询集组合成一个,大多数可能会像 relevant answer 建议的那样使用列表,但你肯定会失去 ORM 功能。
这取决于你的用例,但 Django 我有一个很好的数据库 ORM Database Normalized
table 结构。
将基本字段保留在模型中并将细节保留在另一个模型中是 Database Normalization
逻辑中的最佳方法,因为您可能对不同的 table 进行查询,这不是理想的情况。此时,Django 关系和反向关系为您提供了您所需要的。
考虑到您正在使用多 Table 继承,基于您的示例:
Place.objects.filter(location=x)
Place.objects.filter(location=x, Q(Q(concerthall__hallsize__gt=y)| Q(restaurant__menu=z)))
Place.objects.filter(location=x, concerthall__id__isnull=True)
首先 return 你们 x 的所有餐厅和音乐厅。
第二个 return 你所有的地方都是大厅大小大于 y 的音乐厅或菜单 z 的餐厅。
最后一个是一个超级神奇的查询,它将return你们都安排在不是音乐厅的位置 x。当您有许多从 Place 继承的模型时,这很有用。您可以根据需要将 <model_name>__id
用于 including/excluding table。
您可以构建包含许多 table 的出色 JOINS,并在执行此操作时坚持数据库规范化规则。您会将相关数据保存在一个地方,避免可能出现的数据完整性问题。
这并不是 django 特有的。
一罐模型
Place (with location, name, and other common attributes)
- Restaurant (menu..)
- ConcertHall (hall size..)
- 在两个单独的 table 中,让每个包含他们需要的所有字段。 (在django的世界里,这叫做抽象继承)
- 在三个 table 中,其中一个包含公共字段,另外两个有自己的独特字段。 (django 中的多table 继承)
Two scoops of Django 1.8 书的作者强烈建议不要使用多重 table 继承。
假设您想根据位置查询地点并对结果进行分页(不必是位置,可以是我们要过滤的任何其他常见属性)
我可以看到如何使用 Multi-table 继承来实现它。
select place.id from place LEFT OUTER JOIN "restaurant" on ( restuarant.id=place.id) LEFT OUTER JOIN "concerthall" on ( concerthall.id=place.id) where ... order by distance
用抽象继承来做可行吗?
根据Django documentation: Model inheritance:
The only decision you have to make is whether you want the parent models to be models in their own right (with their own database tables), or if the parents are just holders of common information that will only be visible through the child models.
我认为这两种可能性都只是工具,同样是好的工具,它们是否合适取决于您的用例。当然,这两种方法都有特定的事情需要考虑,而且从概念上讲,有时多重 table 继承可能更难以理解,但除此之外,这个话题变得自以为是。
如果两个模型都需要一个查询集,那么考虑多 table 继承而不是抽象模型是合乎逻辑的,因为否则您将需要将两个查询集组合成一个,大多数可能会像 relevant answer 建议的那样使用列表,但你肯定会失去 ORM 功能。
这取决于你的用例,但 Django 我有一个很好的数据库 ORM Database Normalized
table 结构。
将基本字段保留在模型中并将细节保留在另一个模型中是 Database Normalization
逻辑中的最佳方法,因为您可能对不同的 table 进行查询,这不是理想的情况。此时,Django 关系和反向关系为您提供了您所需要的。
考虑到您正在使用多 Table 继承,基于您的示例:
Place.objects.filter(location=x)
Place.objects.filter(location=x, Q(Q(concerthall__hallsize__gt=y)| Q(restaurant__menu=z)))
Place.objects.filter(location=x, concerthall__id__isnull=True)
首先 return 你们 x 的所有餐厅和音乐厅。
第二个 return 你所有的地方都是大厅大小大于 y 的音乐厅或菜单 z 的餐厅。
最后一个是一个超级神奇的查询,它将return你们都安排在不是音乐厅的位置 x。当您有许多从 Place 继承的模型时,这很有用。您可以根据需要将 <model_name>__id
用于 including/excluding table。
您可以构建包含许多 table 的出色 JOINS,并在执行此操作时坚持数据库规范化规则。您会将相关数据保存在一个地方,避免可能出现的数据完整性问题。