'DJANGO : How to print the value from a class in the prefetch_related class, which calls another class as a Foreign key?

I am very new to Django and tried various answered questions on this forum. But I could not display the TITLE of the Product. I want to display the TITLE for my product from the DB.

From models.py :

class Product(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField()
    description = models.TextField()
    unit_price = models.DecimalField(max_digits=6, decimal_places=2)
    inventory = models.IntegerField()
    last_update = models.DateTimeField(auto_now=True)
    collection = models.ForeignKey(Collection, on_delete=models.PROTECT)
    promotions = models.ManyToManyField(Promotion)


class Order(models.Model):
    PAYMENT_STATUS_PENDING = 'P'
    PAYMENT_STATUS_COMPLETE = 'C'
    PAYMENT_STATUS_FAILED = 'F'
    PAYMENT_STATUS_CHOICES = [
        (PAYMENT_STATUS_PENDING, 'Pending'),
        (PAYMENT_STATUS_COMPLETE, 'Complete'),
        (PAYMENT_STATUS_FAILED, 'Failed')
    ]

    placed_at = models.DateTimeField(auto_now_add=True)
    payment_status = models.CharField(
        max_length=1, choices=PAYMENT_STATUS_CHOICES, default=PAYMENT_STATUS_PENDING)
    customer = models.ForeignKey(Customer, on_delete=models.PROTECT)

class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=models.PROTECT)
    product = models.ForeignKey(Product, on_delete=models.PROTECT)
    quantity = models.PositiveSmallIntegerField()
    unit_price = models.DecimalField(max_digits=6, decimal_places=2)

From views.py :

order = Order.objects.select_related('customer').prefetch_related('orderitem_set__product').order_by('-placed_at')[:5]

From hello.html :

{% for prod in order %}
      <li>Order ID : {{ prod.id }} -- Customer {{ prod.customer.first_name }} -- Product {{ prod.orderitem_set.product.title }}</li>

I have 2 questions here:

  1. In hello.html : How do I display the Product Title?
  2. In the views.py : How do I load and display the promotions from the product class in same call?

Expected output :

Order ID : 408 -- Customer Olin -- Product -- Cheese -- Promotion : xyz
Order ID : 513 -- Customer Merna -- Product -- Milk -- Promotion : xyz
Order ID : 711 -- Customer Rubi -- Product -- Biscuits -- Promotion : xyz
Order ID : 2 -- Customer Nicko -- Product -- Curd -- Promotion : xyz
Order ID : 248 -- Customer Shandeigh -- Product -- Butter -- Promotion : xyz


Solution 1:[1]

The reason it didn't work was because you had more than one orderitem for your order. So you need to add all and then an index.

Change this

<li>Order ID : {{ prod.id }} -- Customer {{ prod.customer.first_name }} -- Product {{ prod.orderitem_set.product.title }}</li>

To this

<li>Order ID : {{ prod.id }} -- Customer {{ prod.customer.first_name }} -- Product {{ prod.orderitem_set.all.0.product.title }}</li>

Maybe you want to loop over the orderitems instead?

views.py

orderObjs = Order.objects.select_related('customer').prefetch_related('orderitem_set__product').order_by('-placed_at')[:5]

orderitems = [item for order in orderObjs for item in order.orderitem_set.all()]

context = {
    "orderitems": orderitems
}

In your html file

{% for orderitem in orderitems %}
    <li>Order ID : {{ orderitem.order.id }} -- Customer {{ orderitem.order.customer.first_name }} -- Product {{ orderitem.product.title }}</li>
{% endfor %}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1