2016-11-28 8 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 %} 

私はを追加210、ページングの場合は1ページあたり25個のアイテムしかないため、ページの読み込み速度は最大18回まで低下し、django-debug-toolによるクエリの量は2から102に増加します。django-debug-tool約25の複製。

どのようにこの遅さを修正できますか?

EDIT:あなたはスピードをしたい場合は、すべての 私の見解

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 = lang_group'ではなく' ...__ iso_code = user_lang'を意味しています。これにより、クエリが102から52に減少しました。 「おそらくあなたが望むのは、個々のメソッドコールではなく、バッチですべてのものを取得することです。 - これはおそらく私が必要なものです:あなたは何かをお勧めできますか?このものをバッチに入れる方法は? – TitanFighter

+2

@TitanFighterクエリを保存するために '.get(city = self.city_id、...)'を使うことができます。または、後で都市が必要な場合は 'Profile.objects.select_related( 'city')'元のクエリで最初は、関連するオブジェクトをフェッチするのではなく、ローカルの外部キー値を使用します。 2番目は、ジョインを使用して、プロファイルをフェッチする同じクエリで都市を取得します。 – knbk

+0

@knbkありがとう。第1の方法とНазарの答えを組み合わせると、27のクエリが得られます。私は 'city_id'トリックを忘れていました:) – TitanFighter

関連する問題