2017-02-10 2 views
0

Lasst uns sagen, dass ich ein einfaches Warenkorb-System mit diesen Modellen haben:Beschriften Summe, während immer noch Zugriff auf Fremdkörper mit

from django.db import models 
from django.utils import timezone 


class Product(models.Model): 
    name = models.CharField(max_length=255) 
    # More fields... 

    @property 
    def featured_image(self): 
     try: 
      return self.productimage_set.all()[0] 
     except IndexError: 
      return None 

    def __str__(self): 
     return self.name 


class ProductImage(models.Model): 
    product = models.ForeignKey(Product, on_delete=models.CASCADE) 
    image = models.FileField(upload_to='products/') 
    # More fields... 

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


class Order(models.Model): 
    created = models.DateTimeField(default=timezone.now) 
    # More fields... 

    def __str__(self): 
     return str(self.pk) 


class OrderItem(models.Model): 
    order = models.ForeignKey(Order, on_delete=models.CASCADE) 
    product = models.ForeignKey(Product, on_delete=models.CASCADE) 
    quantity = models.PositiveIntegerField() 
    # More fields... 

    def __str__(self): 
     return 'Order %s: %s of %s' % (
      self.order_id, 
      self.quantity, 
      self.product.name, 
     ) 

Wenn ein Benutzer einen Auftrag erteilt, ein OrderItem Objekt für jedes Produkt erzeugt wird, sie bestellt , die mich wissen lassen, (1) welches Produkt sie gekauft haben und (2) wie viele von diesem Produkt sie gekauft haben.

Angenommen, ich wollte dem Benutzer zeigen, welche Produkte er am meisten bestellt hat. Ich werde diese Daten als Beispiel:

Order 1: 
Product A: 10 

Order 2: 
Product A: 10 
Product B: 5 

Order 3: 
Product A: 10 
Product B: 5 
Product C: 5 

Diese besondere Anwender sollten die Produkte in dieser Reihenfolge angezeigt:

Product A: 30 total 
Product B: 10 total 
Product C: 5 total 

Dies ist der Code, der diese erreicht:

order_items_by_quantity = OrderItem.objects.values(
    'product__name', 
).annotate(
    total_purchased=Sum('quantity'), 
).order_by(
    '-total_purchased', 
) 

for order_item in order_items_by_quantity: 
    print(order_item) 

Aber mit diesem Ansatz kann ich order_item.product.featured_image nicht verwenden. Gibt es eine Möglichkeit, beides zu haben? Nämlich die Mengen alle summiert und bestellt von den meisten bis mindestens und die Fähigkeit, order_item.product.featured_image zu verwenden.

Antwort

0
order_items_by_quantity = OrderItem.objects.values(
    'product__name', 'product_id' 
).annotate(
    total_purchased=Sum('quantity'), 
).order_by(
    '-total_purchased', 
) 

for order_item in order_items_by_quantity: 
    pid = order_item['product_id'] 
    image = ProductImage.objects.filter(product_id=pid).first() 
    print(order_item, image) 
0

Ich glaube nicht, dass es eine Möglichkeit, Objekteigenschaft zu erhalten, nachdem Sie values() verwenden, wie die queryset dicts mit SELECT-Taste-Werte zurückgibt und keine Objekte modellieren. Sie können zusätzliche Abfrage tun, um Produkte mit ausgewählten Bilder zu erhalten und wo es sich auf Ihre order_items:

order_items_by_quantity = OrderItem.objects.values(
    'product__name', 'product_pk' 
).annotate(total_purchased=Sum('quantity')).order_by('-total_purchased') 

product_image_map = {} 
for product in Product.objects.prefetch_related('productimage_set'): 
    product_image_map[product.pk] = product.featured_image 

for order_item in order_items_by_quantity: 
    order_item['featured_image'] = product_image_map[order_item['product_id']] 

diese Weise können Sie Datenbank fragen einmal für Ihre Produkte, nicht jedes Mal, wenn Sie über order_items_by_quantity laufen. Zusätzlich sollten Sie prefetch_related() auf Ihren Bildern machen.

Verwandte Themen