Question

I have a query that gets me 32 avatar images from my avatar application:

newUserAv = Avatar.objects.filter(valid=True)[:32]

I'd like to combine this with a query to django's Auth user model, so I can get the last the last 32 people, who have avatar images, sorted by the date joined.

What is the best way to chain these two together?

The avatar application was a reusable app, and its model is:

image = models.ImageField(upload_to="avatars/%Y/%b/%d", storage=storage)
user = models.ForeignKey(User)
date = models.DateTimeField(auto_now_add=True)
valid = models.BooleanField()

Note that the date field, is the date the avatar is updated, so not suitable for my purporse

Was it helpful?

Solution

Either you put a field in your own User class (you might have to subclass User or compose with django.contrib.auth.models.User) that indicates that the User has an avatar. Than you can make your query easily.

Or do something like that:

from django.utils.itercompat import groupby
avatars = Avatar.objects.select_related("user").filter(valid=True).order_by("-user__date_joined")[:32]
grouped_users = groupby(avatars, lambda x: x.user)
user_list = []
for user, avatar_list in grouped_users:
    user.avatar = list(avatar_list)[0]
    user_list.append(user)
# user_list is now what you asked for in the first_place: 
# a list of users with their avatars

This assumes that one user has one and only one avatar. Your model allows for more than one avatar per user so you have to watch out not to store more than one.

Explanation of Code Snippet: The avatars of the most 32 recent joined users are requested together with the related user, so there doesn't have to be a database query for any of them in the upcoming code. The list of avatars is then grouped with the user as a key. The list gets all items from the generator avatar_list and the first item (there should only be one) is assigned to user.avatar

Note that this is not necessary, you could always do something like:

for avatar in avatars:
    user = avatar.user

But it might feel more naturally to access the avatars by user.avatar.

OTHER TIPS

It's not possible to combine queries on two different base models. Django won't let you do this (it'll throw an error telling you exactly that).

However, if you have a foreignkey from one model to the other, then adding select_related() to your query will fetch the related objects into memory in a single DB query so that you can access them without going back to the DB.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top