2016-11-28 138 views
0

我需要有多語種網站。爲此,我編寫了django模塊,它收集了大量關於國家,城市及其翻譯幾乎所有語言的信息。如何提高頁面加載速度?

下面是該模塊的型號短版:

class LanguagesGroups(models.Model): 
    class Meta: 
     verbose_name = 'Language Group' 

class Languages(models.Model): 
    iso_code = models.CharField("ISO Code", max_length=14, db_index=True) 
    group = models.ForeignKey(LanguagesGroups, on_delete=models.CASCADE, verbose_name='Group of ISO', 
           related_name='group', db_index=True) 

class Cities(models.Model): 
    population = models.IntegerField(null=True) 
    territory_km2 = models.IntegerField(null=True) 


class CitiesTranslations(models.Model): 
    common_name = models.CharField(max_length=188, db_index=True) 

    city = models.ForeignKey(Cities, on_delete=models.CASCADE, verbose_name='Details of City') 
    lang_group = models.ForeignKey(LanguagesGroups, on_delete=models.CASCADE, verbose_name='Language of city', 
            null=True) 

    class Meta: 
     index_together = (['common_name', 'city'], 
          ['city', 'lang_group']) 

我想展現給用戶有關的地方,其用戶與城市(取決於用戶設置)的翻譯版本要求的一些數據:

class Profile(models.Model): 
    title = models.CharField(_('title'), max_length=120) 
    info = models.TextField(_('information'), max_length=1500, blank=True) 

    city = models.ForeignKey(Cities, verbose_name=_('city'), null=True, blank=True) 

    def get_city(self): 
     user_lang = get_language() # en 
     lang_group = Languages.objects.get(iso_code=user_lang).group # 1823 

     return CitiesTranslations.objects.get(city=self.city, lang_group=lang_group).common_name 

template.html

{% for item in object_list %} 
    {{ item.title }} 
    {{ item.get_city }} 
    {{ item.info }} 
{% endfor %} 

當我添加{{ item.get_city }},在分頁的情況下,每頁只有25個項目,頁面加載速度下降到18倍,查詢量(根據django-debug-tool)從2增加到102. django-debug-tool告訴我約有25個重複。

我該如何解決這個問題?

編輯: 我的觀點

class ProfileListView(ListView): 
    model = Profile 
    template_name = 'profiles/profiles_list.html' 
    context_object_name = 'places_list' 
    paginate_by = 25 

回答

1

首先,如果你想要的速度 - 你應該嘗試caching

您還可以優化您的查詢。

def get_city(self): 
    user_lang = get_language() # en 
    return CitiesTranslations.objects.get(
     city=self.city_id, lang_group__group__iso_code=user_lang 
    ).common_name 

你可能還想要的是讓你的所有東西成批,而不是單獨的方法調用。假設我們有你的object_list

city_ids = [x.city_id for x in object_list] 
city_translations = CitiesTranslations.objects.filter(
    city__in=city_ids, lang_group__group__iso_code=user_lang 
).values_list('city_id', 'common_name') 
city_translations = dict(city_translations) 
for obj in object_list: 
    obj.city_name = city_translations[obj.city_id] 

您可以在某處你的觀點把這個代碼。您還必須在模板中將{{ item.get_city }}更改爲{{ item.city_name }}

+0

您可能是指'...__ iso_code = user_lang'而不是'...__ iso_code = lang_group'。這將查詢從102個減少到52個。不錯。關於「你可能想要的是分批獲取所有東西,而不是單獨的方法調用。」 - 可能這就是我需要的:)你能推薦任何東西,怎麼把這些東西分批? – TitanFighter

+2

@TitanFighter您可以使用'.get(city = self.city_id,...)'來保存查詢,或者如果您稍後需要城市,則可以使用'Profile.objects.select_related('city')'在您的原始查詢中。第一個將使用本地外鍵值而不是獲取相關對象。第二個將使用聯接來獲取提取配置文件的相同查詢中的城市。 – knbk

+0

@knbk謝謝。你的第一種方法結合Назар的回答給了我27個查詢。我忘記了'city_id'技巧:) – TitanFighter