简体   繁体   中英

Django Model how to order by vote time?

So I have three models, User, Post, and UserVote:

User is default django.contrib.auth user

Post definition:

class Post(models.Model):
    num_likes = models.IntegerField(default=0)
    num_dislikes = models.IntegerField(default=0)
 
    # when deleting users, we should simply set user.is_active to False,
    # that way this doesn't break
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    text = models.CharField(max_length=200, default="")

UserVote:

class Action(models.TextChoices):
    UP = 'u'
    DOWN = 'd'

class UserVotes(models.Model):
    voter = models.ForeignKey(User, on_delete=models.CASCADE)
    item = models.ForeignKey(Post, on_delete=models.CASCADE)
    type = models.CharField(max_length=2, choices=Action.choices, default=Action.UP)
    time = models.DateTimeField('time voted on', default=timezone.now)

    class Meta:
        unique_together = ('voter', 'item')

On a user's profile page, I want to return the posts a user upvoted in descending order of when their vote was cast. I'm kind of lost here. I can return the posts a user voted on that aren't theirs as such:

def get_users_liked_posts(user_id):
    Post.objects.filter(uservotes__voter__id=user_id, uservotes__type=Action.UP).exclude(user_id=user_id)

But I'm not sure what to pass to order_by ? It would be something like -uservotes__time but how would I specify that I want to order by a particular user_ids uservotes? I could also retrieve all the uservotes corresponding to a user and order those, but then how would I turn all those into Posts?

EDIT: So after some digging, I found the select_related function: https://www.kite.com/python/docs/django.db.models.QuerySet.select_related

which allows me to do this:

def get_users_liked_posts(user_id):
    # note: position of select_related in query is irrelevant
    upvotes = UserVotes.objects.filter(voter_id=user_id, type=Action.UP).exclude(item__user_id=user_id).order_by('-time').select_related('item')
    return [upvote.item for upvote in upvotes]

It is performant, but I feel like there should be a built in way to do what I'm trying to? I

EDIT2: I'm so dumb, I forgot that I can just .order_by(-time) since I already have the filter in place, whoops

The time when the vote was created is the best attribute to use to order your votes. Use the ordering right in your model definition as such:

class Meta:
    unique_together = ('voter', 'item')
    ordering = ['-time']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM