Python Django-与特定情况相关的预取不';行不通

Python Django-与特定情况相关的预取不';行不通,python,sql,django,orm,django-orm,Python,Sql,Django,Orm,Django Orm,我有三种型号:Trip、City和GoogleAppicityCache 如果我想知道城市的名称,我会在city对象上使用@property,该对象尝试获取当前语言的GoogleAppicityCache 我想减少模板中的查询数量: {% for trip in trips %} {{ trip.city.formatted_address }} {% endfor %} 现在,它在每次迭代中执行新的db查询以查找GoogleAppicityCache。我想预取这些缓存 因此属性fo

我有三种型号:
Trip
City
GoogleAppicityCache

如果我想知道城市的名称,我会在
city
对象上使用
@property
,该对象尝试获取当前语言的
GoogleAppicityCache

我想减少模板中的查询数量:

{% for trip in trips %}
    {{ trip.city.formatted_address }}
{% endfor %} 
现在,它在每次迭代中执行新的db查询以查找
GoogleAppicityCache
。我想预取这些缓存

因此属性
formatted_address
必须找到
GoogleAppicityCache
并从该对象获取
formatted_address

尝试使用
预回迁\u related
,但没有帮助

def profile(request, slug):
    owner = User.objects.filter(userprofile__slug=slug).prefetch_related('trips__city__city_caches').first()
    trips = Trip.objects.filter(user=owner).select_related('city').prefetch_related('city__city_caches')
    return render(request, 'profiles/profile/profile.html', {'owner': owner,'trips':trips})
我的模型:

class Trip(models.Model):
    user = models.ForeignKey('auth.User', related_name='trips')
    city = models.ForeignKey('locations.City', related_name='trips')
    date_from = models.DateField()
    date_to = models.DateField()
    detail = models.TextField(null=True, blank=True)
    # participants = models.ManyToManyField('auth.User', related_name='participating_on_trips', blank=True)
    objects = TripManager()

class City(models.Model):
    ...
    def get_cache_by_lang(self, lang=None, force_refresh=False):
        if not lang:
            lang = get_language() or 'en'
        cache, requested = GoogleApiCityCache.objects.get_or_request(city=self, lang=lang)
        return cache

    @property
    def formatted_address(self):
        return self.get_cache_by_lang().formatted_address

class GoogleApiCityCacheManager(models.Manager):
    def _request_create(self, city, lang):
        """ Create cache (wasn't found) """
        ....
        return cache

    def get_or_request(self, city, lang):
        created = False
        try:
            cache = GoogleApiCityCache.objects.get(city=city, language_code=lang)
        except GoogleApiCityCache.DoesNotExist:
            cache = self._request_create(city, lang)
            created = True
        return cache,created

class GoogleApiCityCache(models.Model):
    language_code = models.CharField(max_length=5)
    api_json_response = JSONField(null=True, blank=True)
    city = models.ForeignKey('locations.City', on_delete=models.CASCADE, related_name='city_caches')
    objects = GoogleApiCityCacheManager()

    class Meta:
        unique_together = ('city', 'language_code')


    @property
    def formatted_address(self):
        try:
            return self.api_json_response['result']['formatted_address']
        except:
            return None

正如您所看到的,
GoogleApiCityCache
for
city
language\u code
可以为无。在这种情况下,会请求Google Api,创建一个新的
GoogleAppicityCache
对象并返回。

当您
预取相关的(“trips城市缓存”)
时,您正在预取
城市缓存。这意味着下面的循环不会导致任何额外的查询

for cache in city.city_caches.all()
    print(cache)
但是,在您的代码
中,格式化的\u地址
调用
get\u cache\u by\u lang
哪个调用
get\u或\u request
哪个调用
GoogleApiCityCache.objects.get()
,这将导致额外的查询

for cache in city.city_caches.all()
    print(cache)
为了利用
prefetch\u related
,您需要重写
get\u cache\u by\u lang
,以便它通过
self.city\u caches.all()
循环找到正确的对象