Working on a Django project, I have a database of users and artworks, the latter of which can be liked. I would like to query, to get how many likes on all their pictures a singular user has together. I am able to write that over two for loops in views.py, but that is slow. I've also written it as a separate (terrible) SQL query, but I'm not certain how to then use it properly, since it's not a query-set anymore (I guess I'd have to query in a way where I get all the required data?).
The end idea is to simply have a table consisting of users, their emails, the number of likes their pictures have received, and the number of images posted. Here are the relevant models (I'm using the default Django auth_user table for users) and the SQL query.
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)
Artwork liked by user:
class Like(models.Model):
artwork = models.ForeignKey(Arts, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
my views.py for loop:
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 query
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)
Is there a way to do this more efficiently?