python - 更高效的 Django (SQL) 查询
问题描述
在一个 Django 项目上工作,我有一个用户和艺术品数据库,后者可以被喜欢。我想查询,以获取单个用户对他们所有图片的点赞数。我可以在views.py 中编写两个for 循环,但这很慢。我也把它写成一个单独的(可怕的)SQL查询,但我不确定如何正确使用它,因为它不再是一个查询集(我想我必须以我获取所有必需的数据?)。
最终的想法是简单地创建一个包含用户、他们的电子邮件、他们的图片收到的赞数以及发布的图片数量的表格。以下是相关模型(我使用默认的 Django auth_user 用户表)和 SQL 查询。
class Arts(models.Model):
user_id = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, unique=False)
title = models.CharField(max_length=100)
description = models.TextField(unique=False, null=False, blank=True)
timestamp = models.DateTimeField(default=timezone.now)
url = models.URLField()
likes = models.IntegerField(default=0)
用户喜欢的艺术品:
class Like(models.Model):
artwork = models.ForeignKey(Arts, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
我的views.py for循环:
def all_users(request):
...
liked = defaultdict()
for user in users_all:
liked[user.id] = 0
for artwork in Arts.objects.filter(user_id=user.id):
liked[user.id] += artwork.likes
...
SQL查询
with connection.cursor() as cursor:
sql = """
WITH lajki AS
(SELECT user_id_id, likes FROM artists_arts ORDER BY likes)
SELECT user_id_id, SUM(likes) AS suma
FROM lajki
GROUP BY user_id_id
ORDER BY suma DESC
"""
cursor.execute(sql)
def namedtuplefetchall(cursor):
desc = cursor.description
nt_result = namedtuple('Result', [col[0] for col in desc])
return [nt_result(*row) for row in cursor.fetchall()]
liked = namedtuplefetchall(cursor)
有没有办法更有效地做到这一点?
解决方案
根本不需要使用原始查询。您可以通过以下方式查询:
从 django.contrib.auth 导入 get_user_model
def all_users(request):
users = get_user_model().objects.annotate(
suma=Sum('arts__likes')
).order_by('-suma')
# …
从此查询集中产生的用户对象将具有一个额外的属性,该属性将对该用户的相关对象.suma
求和。这通常会避免使用临时表,而只需进行一次查询。likes
Arts
但是,我不确定将 存储likes
在Arts
对象中是否是个好主意。这基本上是数据复制(您将聚合形式的数据存储在对象中)。事实证明,即使在同一个数据库上,保持数据同步也更加困难。因此,按对象计算Arts
对象的喜欢可能会更好Like
。
推荐阅读
- error-handling - 当来自服务器的响应缺少必填字段时,是否可以使用状态码?
- javascript - React - 列表元素文本未显示
- .net - 如何在 PowerShell 中添加事件操作处理程序
- javascript - event.wheelDelta 上的触摸板和滚轮
- c# - 在 C# 中使用 Saxon-HE 对 XDocument 执行具有给定上下文的 XQuery
- python - 使用烧瓶运行 SQL 命令并将结果输出为 CSV 下载
- python - 为什么我无法在 Jupyterlab 中使用 BeautifulSoup4 解析本地文件
- c - 在 Do-While 中比较 C 中的字符
- python - 熊猫数据框无法存储十进制值
- python - 如何使用 python 请求库从 Web 下载 PDF 文件