2017-11-03 5 views
0

django adminでは、多対多関係を持つ複数の深く関連するモデルの名前からコンパイルされた__str__()メソッドのモデル名を生成する必要があります。Django Admin Query:深く関連するモデルを照会する複合モデル名を作成

  • 更新

私はコマンドラインからYearlyScheduleモデルを照会すると、prefetch_relatedの使用は、データベースにヒットを容易にするようです。

ただし、この作業は管理者にはできません。

たとえば、prefetch_relatedがない場合、関連する管理ページはデータベースに10回ヒットします。代わりに5 -asにクエリを落とすのModelAdminStackedInlineクラスは、彼らが15

に増やすexpected-のいずれかの方法でget_queryset()prefetch_relatedを使えば、データベースをDDoS攻撃は、INGのwhithoutこのような複雑な問題を達成することは可能ですか?コマンドラインを使用

class DailySchedule(models.Model): 
    hours_keys = models.ManyToManyField(Hour) 
    day = models.Charfield(max...) 

    def __str__(self): 
     return (
      '{0}'.format(
       ','.join(
        hours.__str__() 
        for hours in self.hours_keys.all() 
       ) 
      ) 


class PeriodSchedule(models.Model): 
    weekly_schedule_keys = models.ManyToManyField(DailySchedule) 
    period = models.Charfield(...) 

    def __str__(self): 
    return (
     '{0}'.format(
      '&'.join(
       schedule.__str__() 
       for schedule in self.weekly_schedule_keys.all() 
      ) 
     ) 
    ) 

class YearlySchedule(models.Model): 
    user = models.OneToOneField(Team) 
    period_keys = models.ManyToManyField(PeriodSchedule) 


class YearlyScheduleInline(admin.StackedInline): 
    model = YearlySchedule 

    def get_queryset(self, request): 
     # I tried to put the queryset here: 
     q = (
      super().get_queryset(request) 
      .prefetch_related(...) 
     ) 
     return q 


class TeamAdmin(admin.ModelAdmin): 
    inlines = (YearlyScheduleInline,) 

    def get_queryset(self, request): 
     # I also tried to put the queryset here:    
     ... 

、私は、制御されたデータベースのヒット量のために食料調達するクエリは、次のことができることを考え出し:

q = (
     YearlySchedule.objects 
     .prefetch_related(
      Prefetch(
       'period_keys__weekly_schedule_keys, 
       to_attr='schedule'' 
      ), 
      Prefetch(
       'schedule__hours_keys', 
       to_attr='hours', 
      ), 
     ) 
     .all() 
    ) 

どのように私はそれを効果的に使用するようにジャンゴ管理者に伝えることができますか?

+0

何件のクエリですか?それは恐ろしく見えます。 –

+0

@SebastianWozny実際には2つのクラスで多対多フィールドを省略しているので、少し複雑です!私は単純な組み合わせで9つのクエリを数え、コマンドラインから5に減らしました。私はもう少しテストしなければならない...しかし、管理者は協力していないようだ。私は 'schedule .__ str __()'へのこの呼び出しがキャッシュされた 'select_related'をバイパスしていて、そこから' __str __() 'を呼び出すべきではないのだろうか、あるいは単に - この設計は非効率的です。 – raratiru

答えて

0

this answerからインスピレーションを得て、私はの__str__()メソッドでコンパウンドモデル名を作成するためにカスタムマネージャを作成しました。代わりに、次のコールなど、関連モデルの__str__()方法に頼るの

はありません:

schedule.__str__() for schedule in self.weekly_schedule_keys.all()

...アイデアは使用して、関連するモデル(複数可)からのすべてのデータを収集することですカスタムのマネージャとローカル__str__()方法で文字列をコンパイルします。保存中にそのジャンゴwill not use the custom managerかかわらず心の中で

class PeriodScheduleManager(models.Manager): 
    def get_queryset(self): 
     return( 
      super().get_queryset().prefetch_related(
      Prefetch(
       'weekly_schedule_keys', 
       to_attr='schedule', 
       ), 
      ) 
     ) 

class PeriodSchedule(models.Model): 
    weekly_schedule_keys = models.ManyToManyField(DailySchedule) 
    period = models.Charfield(...) 
    objects = PreiodScheduleManager() 

    def __str__(self): 
     ``` 
     Use all the logic of creating the string with data collected  
     from relative models that the custom manager saves in the 
     relevant attributes using Prefech(to_attr='_'). 

     However, the custom manager is not used when django saves, 
     so return a specific temporary name for this occasion. 
     ```` 
     try: 
      the_string = (
       ... 
       self.schedule 
       ... 
      ) 
      return the_string 
     except AttributeError: 
      return 'A recently saved instance' 

ベア。

関連する問題