2016-08-02 15 views
2

私のアプリケーションでは、トレーニングのリストがあります。このリストの1つのフィールドには、トレーニングごとの予約数が表示されます。django - 別のテーブルから計算されたカウント値を使用してテーブルのレコードをバインドする方法

SELECT * 
FROM club_training a 
LEFT JOIN 
(SELECT training_id, count(*) 
FROM club_booking 
group by training_id) b 
ON a.id = b.training_id 

は、あなたは私のDjangoでそれを行うにはどのようにいくつかのアドバイスを与えることができる:?私はSQLクエリを作成し何を意味するかを表示するには 私のコードでBooking.objects.all().values('training_id').annotate(booked_amount=Count('training_id'))を使用しましたが、結果として、すべてのトレーニングのすべてのカウント値がリストのトレーニングごとに表示されます。各トレーニングに適した1つのカウント値を表示する必要があります。私は他の方向からのアプローチであろう

enter image description here

views.py

class HomePageView(TemplateView): 
    """Home Page with list of trainings""" 
    template_name = 'club/training_list.html' 


    def get_context_data(self, **kwargs): 
     now = datetime.datetime.now() 
     context = super(HomePageView, self).get_context_data(**kwargs) 
     context['trainings'] = Training.objects.filter(state="A", training_date__gte=now).order_by('training_date', 'start_time') 
     for each_training in context['trainings']:  
      each_training.diff = each_training.availability - each_training.counter 
      each_training.counter = Booking.objects.all().values('training_id').annotate(booked_amount=Count('training_id')) 
     return context 

models.py

class Training(models.Model): 
    """Class for plan training""" 
    STATE = (
     ('A', 'Active'), 
     ('I', 'Inactive'), 
    ) 
    name = models.ForeignKey('TrnDesc') 
    instructor = models.ForeignKey('Instructor') 
    start_time = models.TimeField(blank=True) 
    end_time = models.TimeField(default='00:00:00') 
    availability = models.PositiveIntegerField(default=15) 
    state = models.CharField(max_length=1, choices=STATE, default='A') 
    training_date = models.DateField(default=date.today) 
    counter = models.PositiveIntegerField(default=0) 
    def __str__(self): 
     return self.name.name 

class Booking(models.Model): 
    """Data of people which book fitness classes""" 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    email = models.CharField(max_length=50) 
    phone = models.CharField(max_length=10) 
    training = models.ForeignKey('Training') 
    def __str__(self): 
     return self.training.name.name 

training_list.html

{% extends 'club/base.html' %} 

{% block content %} 

     <ul class="nav nav-pills"> 
      <li role="presentation" class="active"><a href="#">Fitness Classes</a></li> 
      <li role="presentation"><a href="#">Join Us</a></li> 
      <li role="presentation"><a href="#">Contact Us</a></li> 
     </ul> 
     <br></br> 
    {% regroup trainings by training_date as date_list %} 
    {% for date in date_list %} 
     <div class="panel panel-default"> 


      <div class="panel-heading">{{date.grouper|date:"l, d F o"}}</div> 


      <table class="table"> 
       <tr> 
        <th style="width: 20%">Training name</th> 
        <th style="width: 30%">Training description</th> 
        <th style="width: 10%">Instructor</th> 
        <th style="width: 10%">Start time</th> 
        <th style="width: 10%">End time</th> 
        <th style="width: 10%">Left</th> 
        <th style="width: 10%">Test_counter</th> 
        <th style="width: 10%">Actions</th> 
       </tr> 


       {% for training in date.list %} 

       <tr> 
        <td>{{training.name}}</td> 
        <td>{{training.name.desc}}</td> 
        <td>{{training.instructor}}</td> 
        <td>{{training.start_time|time:"H:i"}}</td> 
        <td>{{training.end_time|time:"H:i"}}</td> 
        <td>{{training.diff}}</td> 
        <td>{{training.counter}}</td> 
        <td><a href="{% url 'book' training_id=training.pk%}"><button type="button" class="btn btn-primary">Book</button></a></td> 
       </tr> 

       {% endfor %}  
      </table> 
     </div> 
    {% endfor %} 

{% endblock %} 
+0

**とのためにそのいくつかの良い食べ物* * training_idでグループ化された、すべての予約グループの予約オブジェクトの数**。私はそれを正しく理解したのか、それとも他に何かしたいのですか? –

+0

自分のトレーニングリストに、各トレーニングの予約オブジェクトの数を表示したい(各training_idに対して) – annlii

答えて

1
for each_training in context['trainings']:  
     each_training.diff = each_training.availability - each_training.counter 
     each_training.counter = Booking.objects.filter(training_id=each_training.id).count() # just modify this line 
    return context 
+0

スタックオーバーフローへようこそ:-) [回答] – JimHawkins

+0

@annliiをご覧ください。これは答えの1つです。しかし、技術的に '' training '' 'に' n'個の訓練オブジェクトがあれば、 'n個の' Booking.objects.filter(training_id = each_training.id).count() 'クエリをあなたに送りますデータベース。したがって、 'n'の値が上がると、** DjangoDebugToolbar **を使ってページを読み込むのに時間がかかりすぎるのを見ることができます。あなたがSQLのために書いた同等のクエリは、あなたが望むすべてのものを返すクエリでした。 –

+0

@AnkushRaghuvanshiその問題に気づいてくれてありがとう。今のところ私にとっては大丈夫ですが、後で私はおそらくより効率的になるでしょう。 – annlii

0

each_training.booking_set.count()

また、私はそれはあなたのデータベースの目標に合うわからないんだけど、私はあなたが探しているものを理解していれば、あなたはこのようにそれを設定できます。

models.py

class Training(models.Model): 
    ... 
    <fields> 
    ... 
    def __str__(self): 
     return self.name.name 

    @property 
    def counter(self): 
     return self.booking_set.count() 

    @property 
    def diff(self): 
     return self.availability - self.counter 

このように、値はモデルからテンプレートに直接行くことができます。

私が見ることができる唯一の問題は、これらのフィールドがクエリーセットに含まれないようにすることだと思います。たとえば、Training.objects.filter(counter__gt=0)は機能しません。必要な場合は、データベースの値を保存して更新する機会を見つける必要があると思います。possibly using a signal、ビューを呼び出すたびに値を何度も何度も保存する必要はありません。

managers.py

from django.db.models import Manager 

class Active(Manager): 

    def by_date(self, date) 
     Training.objects.filter(state="A", training_date__gte=date).order_by('training_date', 'start_time') 

次に、あなたがあなたに管理者を追加することができます。それはまた、あなたがビューでやっているロジックの一部を処理するためにマネージャーを使用することができますように見えます

モデル(あなたのバニラマネージャーを維持することを確認さ):

models.py

from .managers import Courses 

class Training(models.Model): 
    ... 
    <fields> 
    objects = models.Manager() 
    active = Active() 
    ... 

    def __str__(self): 
     return self.name.name 

これで、すべての情報をスリムなListViewで配布することができます。

from django.views.generic import ListView 

class HomePageView(ListView): 
    """Home Page with list of trainings""" 
    template_name = 'club/training_list.html' 
    context_object_name = "trainings" 

    def get_queryset(self): 
     now = datetime.datetime.now() 
     return Trainings.active.by_date(now) 

私はあなたがテンプレートにやっていることのいくつかに慣れていないんだけど、すべてが、それは今と同じ方法を動作するはずです。

それとも私が道オフだけど、うまくいけば思考:)私は右のそれを取得していた場合、あなたは**トレーニングIDを取得したいので、

+0

'@プロパティ 'を定義すると、そのプロパティの値がデータベースに格納されないため、その要件の時間。だから、技術的に 'def counter'を使うと、ページロード時に各オブジェクトのカウント値を計算するだけで、ページの読み込み速度が遅くなります。したがって、オブジェクトの数が多く、計算が多すぎると速度が遅くなります。 –

関連する問題