Using fields from a aggregated QuerySet in a django template

Viewed 65

So I got a QuerySet result from an aggregate function to display in a low-spec eBay clone of mine. But my problem is displaying certain fields in the Django template as I want, for example, I want to display the highest bidder's username and bid. When I call the whole object itself like so {{winner}}, then it displays. But when I try to access its fields like so {{winner.user_id.username}}, I get no output although the QuerySet does execute.

When I try to get a field like so (winner.user_id.username): enter image description here

When I only call winner: enter image description here

models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

CATEGORIES = [
        ('Appliances', 'Appliances'),
         ('Tech', 'Tech'), 
         ('Gaming', 'Gaming'), 
         ('Fashion', 'Fashion'), 
         ('Sports and Fitness','Sports and Fitness'), 
         ('Other','Other'),
         ("Hygiene and Medicine","Hygiene and Medicine"), 
         ("Stationery","Stationery"),
        ('Decor', 'Decor'), 
        ('Furniture','Furniture'), 
        ('Cars and Mechanical Things','Cars and Mechanical Things'), 
        ("Tools","Tools")
    ]

# Create models here
class User(AbstractUser):
    pass

class Auction_Listing(models.Model):
    user_id = models.IntegerField(default=1)
    list_title = models.CharField(max_length=64)
    desc = models.TextField(max_length=600)
    img_url = models.URLField(max_length=200, null=True, blank=True)
    start_bid = models.IntegerField()
    category = models.CharField(choices=CATEGORIES, max_length=35, null=True, blank=True)
    active = models.BooleanField(default=True)

    def __str__(self):
        return f"ID:{self.id}, {self.list_title}: {self.desc}, {self.start_bid} posted by user:{self.user_id} in Category:{self.category}, url:{self.img_url}"

class Bids(models.Model):
    user_id = models.ForeignKey('User', on_delete=models.CASCADE)
    auctions = models.ForeignKey('Auction_Listing', on_delete=models.CASCADE, default=1,related_name='bidauc')
    bid = models.IntegerField()

    def __str__(self):
        return f"ID:{self.id}, Bid {self.bid} posted by user:{self.user_id} on auction {self.auctions}"

class Auction_Comments(models.Model):
    user_id = models.ForeignKey('User', on_delete=models.CASCADE)
    comment = models.TextField(max_length=324, default='N/A')
    auctions = models.ForeignKey('Auction_Listing', on_delete=models.CASCADE, default=1,related_name='comauc')

    def __str__(self):
        return f"ID:{self.id}, Comment: {self.comment} posted by user:{self.user_id} on auction {self.auctions}"

class Watchlist(models.Model):
    user_id = models.ForeignKey('User', on_delete=models.CASCADE)
    auctions = models.ForeignKey('Auction_Listing', on_delete=models.CASCADE, default=1, related_name='watchauc')

    def __str__(self):
        return f"ID:{self.id}, user:{self.user_id} on auction {self.auctions}"

views.py

def render_listing(request, title):
    if request.method == "POST":
        form = BidForm(request.POST)
        bid = int(request.POST['new_bid'])
        listing = Auction_Listing.objects.get(list_title=title)
        comments = Auction_Comments.objects.filter(auctions=listing)
        if bid <= listing.start_bid:
            error = True
        else:
            error = False
            listing.start_bid = bid
            listing.save()
            new_bid = Bids(user_id=request.user, auctions=listing, bid=bid)
            new_bid.save()
        return render(request, 'auctions/listing.html', {
            "listing": listing,
            "form": form,
            "comments": comments,
            "error": error,
            "comform": CommentForm()
        })
    else:
        form = BidForm()
        comform = CommentForm()
        listing = Auction_Listing.objects.get(list_title=title)
        comments = Auction_Comments.objects.filter(auctions=listing)
        high_bid = Bids.objects.filter(auctions=listing).aggregate(maximum=Max("bid"))
        winner = Bids.objects.filter(auctions=listing, bid=high_bid['maximum'])
        print(winner)
        return render(request, 'auctions/listing.html', {
            "listing": listing,
            "form": form,
            "comments": comments,
            "error": False,
            "comform": comform,
            "winner": winner
        })

template's code:

{% extends "auctions/layout.html" %}

{% load static %}

{% block title %} Listing: {{listing.list_title}} {% endblock %}

{% block body %}
    {% if listing.active %}
    <h2>{{ listing.list_title }}</h2>

    <div class='listing'>
        {% if listing.img_url == "" or listing.img_url == None %}
            <a href='#'><img src="{% static 'auctions/img404.png' %}" class='img-fluid'></a>
        {% else %}
            <a href='#'><img src="{{ listing.img_url }}" class="img-fluid" alt='image of {{ listing.list_title }}'></a>
        {% endif %}
        <p>
            {{ listing.desc }}
        </p>
        <p>
            Current Bid: ${{ listing.start_bid }}
        </p>
        <p>Category: {{ listing.category }}</p>
        
        <p></p>
        {% if user.is_authenticated %}
            <div class="bid">
                <a href='{% url "watch" listing.list_title %}' class='btn btn-primary'>Add to/Remove from Watchlist</a>
                {% if listing.user_id == user.id %}
                    <a href='{% url "close" listing.list_title %}' class='btn btn-primary'>Close Auction</a>
                {% endif %}
            </div>
            <div class="bid">
                <h3>Bid:</h3>
                <form method="POST" action='{% url "renlist" listing.list_title %}'>
                    {% csrf_token %}
                    {{form}}
                    <button type="submit" class='btn btn-primary'>Make New Bid</button>
                    {% if error %}
                        Please enter a bid higher than the current bid.
                    {% endif %}
                </form>
            </div>
        {% else %}
            <p><a href='{% url "register" %}' class='register'>Register</a> to bid on this item and gain access to other features</p>
        {% endif %}
    </div>
    <div class="listing">
        <h3>Comments:</h3>
        {% if user.is_authenticated %}
            <div id='comform'>
                <h4>Post a Comment</h4>
                <form method="POST" action="{% url 'commentadd' %}">
                    {% csrf_token %}
                    {{comform}}
                    <button type="submit" class="btn btn-primary">Post Comment</a>
                </form>
            </div>
        {% endif %}
        <p>
            {% for comment in comments %}
                <div class="comment">
                    <h4>{{comment.user_id.username}} posted:</h4>
                    <p>{{comment.comment}}</p>
                </div>
            {% empty %}
            <h4>No comments as of yet</h4>
            {% endfor %}
        </p>
    </div>
    {% else %}
        <h2>This auction has been closed</h2>
        <div>
            <a href='{% url "watch" listing.list_title %}' class='btn btn-primary'>Add to/Remove from Watchlist</a>
        </div>
        <p>{{winner.user_id.username}}</p>
    {% endif %}
{% endblock %}

Thanks in advance for the help!
Kind Regards
PrimeBeat

1 Answers

This will give a QuerySet. You can see in your second image.

A QuerySet represents a collection of objects from your database.

winner = Bids.objects.filter(auctions=listing, bid=high_bid['maximum'])

You need to iterate over that QuerySet, get whatever data you want and show it in your template.

{% for win in winner %}
 <p>{{ win.user_id.username }}</p>
{% endfor %}
Related