django 如何迭代查询集的查询集?

r6vfmomb  于 2023-08-08  发布在  Go
关注(0)|答案(3)|浏览(100)

我尝试遍历与Album QuerySet关联的Review QuerySet,以便收集Review QuerySet中的总评分。(例如,9 + 8 + 7 + 9 = 33)以下是我的模型:

class Album(models.Model):
    creator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    artist = models.CharField(max_length=255)
    title = models.CharField(max_length=255)
    # image =
    rating = models.IntegerField(
        choices=[(i, i) for i in range(1, 11)],
        validators=[MaxValueValidator(10), MinValueValidator(1)],
        default=10,
    )
        ...

class Review(models.Model):
    reviewer = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    album = models.ForeignKey(Album, on_delete=models.CASCADE)
    rating = models.IntegerField(
        choices=[(i, i) for i in range(1, 11)],
        validators=[MaxValueValidator(10), MinValueValidator(1)],
        default=10,
    )
        ...

字符串
下面是我尝试for循环来尝试并获得这些总数:

# Attempts working off of: `all_albums = Album.objects.all()`

# Attempt 1
>>> for album in all_albums:
...     review_ratings_amount = album.review_set.rating.all()
...     print(review_ratings_amount)

# Attempt #2
>>> for album in all_albums:
...     review_ratings = album.review_set.filter("rating")
...     print(review_ratings)

# Attempt #3
>>> for album in all_albums:
...     review_ratings = album.review_set.get(rating)
...     print(review_ratings)

# Attempt #4
>>> for album in album_ratings:
...     review_ratings = album.review_set.get("rating")
...     for rating in review_ratings:
...             print(rating)

# Attempt 5 (this was an attempt to see if ANYTHING would return, and I actually got some QuerySets in return so I think
# this one might be in the vicinity of the right track)
>>> for album in all_albums:
...     print(album.review_set.values())

# Attempt #6
>>> for album in all_albums:
...     print(album.review_set.get('rating'))

# Attempt #7
>>> for album in all_albums:
...     items = Album.objects.all().values()
...     for item in items:
...             print(item.review_set)

# Attempt 8
>>> for album in all_albums:
...     review_ratings = Album.objects.get('review').values()
...     print(review_ratings)

# Attempt 9
>>> for album in all_albums:
...     review_ratings = Album.objects.get('review.rating')
...     print(review_ratings)

# Attempt 10
>>> for album in all_albums:
...     review_ratings = Album.objects.get('review.rating')
...     for review in review_ratings:
...             print(dict(review))


上面所有的尝试都返回了错误,除了# Attempt 5,它返回了album.review_set.values()中所有值的查询集--所以我认为我可能接近这段代码的“正确轨道”。
但是谁能给我一些有用的文件吗?

ltskdhd1

ltskdhd11#

您需要了解访问review_set时返回的对象。正如您所理解的那样,它是一个QuerySet,但是您的一些尝试尝试访问rating属性。如果您将查询集视为对象列表,那么您将尝试获得列表的评级,而不是对列表中的每个对象进行评级。
下面的方法会让你得到你想要的东西,尽管还有更多的方法可以实现同样的目标。

>>> for album in all_albums:
...     review_ratings = album.review_set.values_list("rating", flat=True)
...     print(review_ratings)
...     total_ratings = sum(review_ratings) # to get the sum total of ratings

字符串
查询集的values_list返回传递属性的元组,如果只有一个属性被传递给values_list,flat=True将返回单个值而不是1元组(例如,[1]而不是[(1,),])。

nzk0hqpo

nzk0hqpo2#

这是根据记忆来的所以我可能搞错了...
album.review_set是对象管理器,而不是查询集。对象管理器的另一个例子是Album.objects。要从对象管理器获取QuerySet,需要使用.all().values()(正如您所发现的那样)、迭代上下文等。
所以,不是你想要的,但这应该运行:

for album in all_albums:
    for review in album.review_set.all():
        print(review.rating)

字符串
您可能希望使用“聚合”数据库函数来获得平均评论或类似的东西。

编辑:

Django文档有一些很好的例子来说明你在做什么与评级。

>>> from django.db.models import Avg
>>> Album.objects.aggregate(average_rating=Avg("review__rating"))


然后每个Album对象都有一个average_rating属性。(我没有测试过这个)

6jygbczu

6jygbczu3#

>>> for album in all_albums:
...     print(album.review_set.values())

字符串
好的,你有一个神秘的物体,album,有一个review_set属性,你不确定如何与它们交互。这里有一些建议。tl;dr:dir()type()help()是您的好友。
从类定义开始。你发布了一些,但我没有注意到review_set在那里。它可能是...省略号的一部分。阅读它的来源--你可能会在那里找到一些线索。
向RDBMS询问表模式,或者使用简单的SELECT * 查询来调查它。我们期望模型对象与数据库存储的内容相似。
假设你有一个完全未知的对象,并且没有文档网站。我们该如何调查它以找出它的好处?
准备工作:你会发现pp很方便,所以把它拉进去。

>>> from pprint import pp


(1.)问type对象是什么:

>>> type(album)


你也可以使用print(type(album))。在你的例子中,album.review_set可能是你更感兴趣的对象。
(2.)请求对象上的help

>>> help(album)


如果有“docstring”“,则会显示它。大多数对象都有一堆属性,每个属性都有自己的docstring,它们也会被显示出来。
(3.)检查对象的属性:

>>> pp(dir(album))


你不需要 * 漂亮地打印dir输出,但这样会更易读。
每个属性本身就是一个对象,您可以继续研究任何被证明有趣的属性。例如,下一步可能是查看pp(dir(album.review_set))
祝你好运!

相关问题