2015-01-28 2 views
0

От https://docs.djangoproject.com/en/dev/ref/models/conditional-expressions/ и https://docs.djangoproject.com/en/dev/ref/models/expressions/ Я вижу, что я могу сделать более сложную аннотацию с Django 1.8.Комплексная аннотация в Django 1.8

Обычно я хотел бы использовать

return qs.extra(select={ 
    my_sum: " 
    SELECT SUM(price) 
    FROM some_table_name 
    WHERE group_id IN (
     SELECT m2.id 
     FROM other_table_name m2 
     WHERE m2.some_field_name = 'some value' 
    ) 
    "}) 

Будет ли это возможно с дополнительными функциями в Django ORM?

+0

вау, это удивительный – yuvi

+0

Приятно видеть Django ORM заимствуя некоторые черты из 'sqlalchemy.sql'. –

ответ

0

Вышеуказанное возможно и распространяется на Django Documentation on Conditional Aggregation.

В примере, они показывают модель

from django.db import models 

class Client(models.Model): 
    REGULAR = 'R' 
    GOLD = 'G' 
    PLATINUM = 'P' 
    ACCOUNT_TYPE_CHOICES = (
     (REGULAR, 'Regular'), 
     (GOLD, 'Gold'), 
     (PLATINUM, 'Platinum'), 
    ) 
    name = models.CharField(max_length=50) 
    registered_on = models.DateField() 
    account_type = models.CharField(
     max_length=1, 
     choices=ACCOUNT_TYPE_CHOICES, 
     default=REGULAR, 
    ) 

, а затем выполнить агрегацию на нем:

>>> from django.db.models import IntegerField, Sum 

>>> Client.objects.aggregate(
    regular=Sum(
     Case(
      When(account_type=Client.REGULAR, then=1), 
      output_field=IntegerField() 
     ) 
    ), 
    gold=Sum(
     Case(
      When(account_type=Client.GOLD, then=1), 
      output_field=IntegerField() 
     ) 
    ), 
    platinum=Sum(
     Case(
      When(account_type=Client.PLATINUM, then=1), 
      output_field=IntegerField() 
     ) 
    ) 
) 

>>> {'regular': 2, 'gold': 1, 'platinum': 3} 

Так что да, это возможно. Учитывая ваш пример выше, было бы по линии:

from django.db.models import IntegerField, Sum 

SomeTable.objects.aggregate(
    price_sum=Sum(
     Case(
      When(other_model__some_field_name='some_value', then='price'), 
      default=0, 
      output_field=IntegerField() 
     ) 
    ) 
) 
+0

Проблема в том, что мне нужен этот запрос внутри дополнительного тега, то есть 'MyModel.objects.extra (select = {my_sum:" SELECT SUM (цена) FROM some_table_name ... 'поэтому я боюсь, что это не так просто :( – Jamgreen

+0

Итак, 'my_sum' - это переменная, которая передается внутри, так что, когда вы вызываете' instance. <Имя_машины my_sum> ', вы получаете сумму для экземпляра этого конкретного объекта, а не общую сумму? EG' my_sum = 'price_sum'', то 'instance.price_sum' выдает аннотированную цену. –

Смежные вопросы