在 django 模板中使用聚合 QuerySet 中的字段

Posted

技术标签:

【中文标题】在 django 模板中使用聚合 QuerySet 中的字段【英文标题】:Using fields from a aggregated QuerySet in a django template 【发布时间】:2021-10-13 19:10:48 【问题描述】:

所以我从一个聚合函数中获得了一个 QuerySet 结果,以显示在我的低规格 eBay 克隆中。但我的问题是根据需要在 Django 模板中显示某些字段,例如,我想显示最高出价者的用户名和出价。当我像winner 那样调用整个对象本身时,它就会显示出来。但是当我尝试像winner.user_id.username 那样访问它的字段时,尽管 QuerySet 确实执行了,但我没有得到任何输出。

当我尝试获取这样的字段时 (winner.user_id.username):

当我只打电话给winner时:

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
        )

模板代码:

% 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 %

提前感谢您的帮助! 亲切的问候 PrimeBeat

【问题讨论】:

【参考方案1】:

这将给出一个QuerySet您可以在第二张图片中看到。

QuerySet 代表数据库中对象的集合。

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

您需要遍历该 QuerySet,获取所需的任何数据并将其显示在模板中。

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

【讨论】:

以上是关于在 django 模板中使用聚合 QuerySet 中的字段的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Django QuerySet 生成总和并在模板中显示?

Django 1.10中文文档-聚合

在 Django 中过滤 Queryset 并设计正确的 urls.py 和模板

Django的注释和聚合方法之间的区别?

Django Queryset 不同视图的相同模板

django 中的聚合函数,分组函数,F 查询, Q查询