2017-08-04 8 views
1

次の2つのモデルがあります。django - annotate() - 別の列のフィルタを持つ列のSum()

class Product(models.Model): 
    product_group=models.ForeignKey('productgroup.ProductGroup', null=False,blank=False) 
    manufacturer=models.ForeignKey(Manufacturer, null=False,blank=False) 
    opening_stock=models.PositiveIntegerField(default=0) 

    class Meta: 
     unique_together = ('product_group', 'manufacturer') 

TRANSACTION_TYPE=(('I','Stock In'),('O','Stock Out')) 
class Stock(models.Model): 
    product=models.ForeignKey('product.Product', blank=False,null=False) 
    date=models.DateField(blank=False, null=False,) 
    quantity=models.PositiveIntegerField(blank=False, null=False) 
    ttype=models.CharField(max_length=1,verbose_name="Transaction type",choices=TRANSACTION_TYPE, blank=False) 
私は stock_in_sum=Sum(of all stock ins)ですべての製品をリストする必要が

stock_out_sum=Sum(of all stock outs)blance_stock=opening_stock+stock_in_sum - stock_out_sum

これは私がこれまで達成してきたものです。

class ProductList(ListView): 
    model=Product 

    def get_queryset(self): 
     queryset = super(ProductList, self).get_queryset() 
     queryset = queryset.prefetch_related('product_group','product_group__category','manufacturer') 
     queryset = queryset.annotate(stock_in_sum = Sum('stock__quantity')) 
     queryset = queryset.annotate(stock_out_sum = Sum('stock__quantity')) 

私は、各製品のオブジェクトと一緒にproduct.opening_stock + stock_in_sum - stock_out_sum

としてsum(quantity) where ttype='O'

  • blance_stockとしてsum(quantity) where ttype='I'
  • stock_out_sumとして

    1. stock_in_sumを取得する必要があります。

      どうすればよいですか?

      ありがとうございました。

  • 答えて

    2

    あなたはあなたではなく、複数のassignationsの異なる操作を、連鎖することができます合計を作るためにconditional aggregation

    queryset = queryset.annotate(
        stock_in_sum = Sum(Case(When(stock__ttype='I', then=F('stock__quantity')), output_field=DecimalField(), default=0)), 
        stock_out_sum = Sum(Case(When(stock__ttype='O', then=F('stock__quantity')), output_field=DecimalField(), default=0))) 
    ) 
    

    を使用し、その後F() expression

    queryset = queryset.annotate(balance_stock=F('opening_stock') + F('stock_in_sum') - F('stock_out_sum')) 
    

    でバランスを計算することができます:

    queryset = queryset.prefetch_related(...).annotate(...).annotate(...) 
    
    +0

    ありがとう! ExpressionWrapper()を使用するように私に尋ねました。 'クエリセット= queryset.annotate( \t \t stock_in_sum =合計(ケース((stock__ttype = 'I' は、次に= ExpressionWrapper(F( 'stock__quantity')、 \t \t \t \t \t \t次のように最初の二つのデータを得\t \t \t \t \t \t \t \t出力フィールド= DecimalFieldは())))) \t \t) \t \t \t \t \t \t queryset = queryset。( \t \t stock_out_sum =合計(ケース((stock__ttype = 'O' は、= ExpressionWrapper(F( 'stock__quantity')、 \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \tに注釈を付けます\t output_field = DecimalField()))))) \t \t \t \t – art06

    +0

    しかし 'クエリセット= queryset.annotate( \t \t balance_stock = ExpressionWrapper(F( 'opening_stock')+ F( 'stock_in_sum') - F( 'stock_out_sum')、出力フィールド= DecimalFieldは()) \t \tは)' Noneを与えません'stock_in_sum'または' stock_out_sum'のいずれかを持つすべての行がNoneです。 – art06

    +0

    私はどこかでNoneの代わりに0を返す必要があるように見えますが、方法はわかりません。 – art06

    関連する問題