与特定情况相关的Django预取

2024-09-30 08:30:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有三个模型:TripCity和{}。在

如果我想知道城市的名称,我在City对象上使用@property,该对象试图获取当前语言的GoogleApiCityCache。在

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

{% for trip in trips %}
    {{ trip.city.formatted_address }}
{% endfor %} 

现在,它执行新的db查询以在每次迭代中查找GoogleApiCityCache。我想预取这些缓存。在

所以属性formatted_address必须找到一个GoogleApiCityCache,并从这个对象中得到formatted_address。在

试图使用prefetch_related,但没有帮助。在

^{pr2}$

我的模型:

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对于citylanguage_code可以是none。在本例中,请求googleapi,创建一个新的GoogleApiCityCache对象并返回。在


Tags: selftruecitycachelanggetreturnaddress
1条回答
网友
1楼 · 发布于 2024-09-30 08:30:44

当您prefetch_related('trips__city__city_caches')时,您正在预取city_caches。这意味着下面的循环不会引起任何额外的查询。在

for cache in city.city_caches.all()
    print(cache)

但是,在代码中formatted_address调用get_cache_by_lang,后者调用get_or_request,后者调用{},这将导致额外的查询。在

为了利用prefetch_related,您需要重写get_cache_by_lang,以便它遍历{}以找到正确的对象。在

相关问题 更多 >

    热门问题