2017-07-24 2 views
0

J'ai les deux modèles suivants.django ListView - Queryset personnalisé en joignant avec un autre modèle

class Product(models.Model): 
    product_group=models.ForeignKey('productgroup.ProductGroup', null=False,blank=False) 
    manufacturer=models.ForeignKey(Manufacturer, null=False,blank=False) 
    product_type=models.CharField(max_length=2, choices=PRODUCT_TYPE, null=False,blank=False) 
    wheel_position=models.CharField(max_length=1, choices=FRONT_BACK, null=False,blank=False) 
    opening_stock=models.PositiveIntegerField(default=0) 

    class Meta: 
     ordering=['product_group','manufacturer'] 
     unique_together = ('product_group', 'manufacturer','product_type','wheel_position') 


    def get_total_stock_in(self): 
     sum=Stock.objects.filter(product=self.id, ttype='I').aggregate(Sum('quantity')) 

     if sum['quantity__sum'] is not None: 
      return sum['quantity__sum'] 
     else: 
      return 0 

    def get_total_stock_out(self): 
     sum=Stock.objects.filter(product=self.id, ttype='O').aggregate(Sum('quantity')) 
     if sum['quantity__sum'] is not None: 
      return sum['quantity__sum'] 
     else: 
      return 0 

    def get_balance_stock(self): 
     return (self.opening_stock+self.get_total_stock_in() 
       - self.get_total_stock_out()) 

et

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) 
    added_date=models.DateTimeField(blank=False, auto_now=True) 

J'ai une sous-classe ListView à la liste tous les produits.

class ProductList(ListView): 
    model=Product 
    paginate_by = 20 

    def get_queryset(self): 
     queryset = super(ProductList, self).get_queryset() 
     queryset = queryset.prefetch_related('product_group','product_group__category','manufacturer') 
     return queryset.order_by('product_group__category','product_group') 

Je dois montrer l'total stock in, total stock out et available balance ainsi que chaque produit dans la liste vue.

En ce moment, j'appelle les fonctions get_total_stock_in(), get_total_stock_out() et get_balance_stock() définies dans le Product model. Mais cela crée beaucoup de requêtes répétées sur la base de données.

Comment ajouter ces données dans le jeu de requêtes de ListView?

Merci pour toute aide.

Répondre

0

Permettez-moi de poster la solution ici.

J'ai ma solution avec l'aide d'un autre fil à django - annotate() - Sum() of a column with filter on another column

Voici mon ListView en ce moment.

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(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)) 
     ) 
     queryset = queryset.annotate(
     balance_stock = ExpressionWrapper(F('opening_stock') + F('stock_in_sum') - F('stock_out_sum'), output_field=DecimalField()) 
     ) 

     return queryset