技术开发 频道

高性能Web开发:减少数据库往返实例

  能支持多深的关系?

  要跨多个级别时怎么办?select_related 和prefetch_related都可以通过双下划线遍历关系对象。用这个功能时,中间对象也会包括在内。这很有用,但在更复杂的对象模型中有点难用。

# only works when there's a single object at each step
city = City.objects.select_related(
'state__country').all()[0]
# 1 query, no further db queries
print(
'{0} - {1} - {2}'.format(city.name, city.state.name,
                               city.state.country.name)

# works for both single and multiple object relationships
countries = Country.objects.prefetch_related(
'states__cities')
# 3 queries, no further db queries
for country in countries:
    for state in country.states:
        for city in state.cities:
            print(
'{0} - {1} - {2}'.format(city.name, city.state.name,
                                           city.state.country.name)

  prefetch_related用在原生查询

  最后一点。上周的 efficiently querying for nearby things 一文中,为了实现查找最近的经度/纬度点,我写了一条复杂的SQL。其实最好的方法是写一条原生的sql查询 。而原生查询不支持prefetch_related,挺可惜的。但有一个变通的方法,即可以直接用Django实现prefetch_related功能的prefetch_related_objects。

from django.db.models.query import prefetch_related_objects

# prefetch_related_objects requires a list, it won
't work on a QuerySet so
# we need to convert with list()
cities = list(City.objects.raw(
'<sql-query-for-nearby-cities>'))
prefetch_related_objects(cities, (
'state__country',))
# 3 queries, no further db queries
for city in cities:
    print(
'{0} - {1} - {2}'.format(city.name, city.state.name,
                                   city.state.country.name)
0
相关文章