Python 更高效的Django(SQL)查询

Python 更高效的Django(SQL)查询,python,sql,django,Python,Sql,Django,在Django项目中,我有一个用户和艺术品数据库,后者很受欢迎。我想查询一下,一个单一的用户在他们所有的图片上有多少喜欢的人。我可以在views.py中为循环编写两个以上的代码,但速度很慢。我还将其编写为一个单独的(糟糕的)SQL查询,但我不确定如何正确使用它,因为它不再是一个查询集(我想我必须以一种获得所有必需数据的方式进行查询) 最终的想法是简单地创建一个由用户、他们的电子邮件、他们的图片收到的喜欢的数量以及发布的图片数量组成的表。下面是相关的模型(我使用默认的Django auth_use

在Django项目中,我有一个用户和艺术品数据库,后者很受欢迎。我想查询一下,一个单一的用户在他们所有的图片上有多少喜欢的人。我可以在views.py中为循环编写两个以上的代码,但速度很慢。我还将其编写为一个单独的(糟糕的)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)
用户喜欢的艺术品:

my views.py for循环:

SQL查询


有没有办法更有效地执行此操作?

根本不需要使用原始查询。您可以使用以下工具进行查询:

从django.contrib.auth导入get\u user\u模型

def all_users(request):
    users = get_user_model().objects.annotate(
        suma=Sum('arts__likes')
    ).order_by('-suma')
    # …
def所有用户(请求):
users=get\u user\u model().objects.annotate(
suma=Sum(‘艺术’)
).order_by('-suma'))
#…
由此查询集生成的用户对象将具有一个额外属性
.suma
,该属性将对该用户的相关
艺术
对象的
进行求和。这通常会避免使用临时表,只进行一次查询


但是,我不确定将
likes
存储在
Arts
对象中是否是一个好主意。这基本上是数据复制(在对象中存储聚合形式的数据)。事实证明,即使在同一个数据库上,保持数据同步也比较困难。因此,通过
Like
对象来计算
艺术
对象的Like可能更好。

。annotate正是我想要的。我认为有一个很好的方法可以将这两个模型分组,但就是想不出来。非常感谢你。至于对艺术的喜爱,是的,我们在制作表格时注意到了这一点,但到那时我们还是保持原样。不过,我会设法解决它。
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
...
    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)
def all_users(request):
    users = get_user_model().objects.annotate(
        suma=Sum('arts__likes')
    ).order_by('-suma')
    # …