简体   繁体   中英

Django ORM - Get N random records, and then split them in 2 groups

I have a Post model:

class Post(models.Model):
    headline = models.CharField(max_length=255)
    ...

What I am, unsuccessfully, trying to achieve, is to get two random groups of 5 posts each, where the 2nd group records that the 1st group does NOT have.

Now I know how to do this using Python, but I was wondering if there is a more elegant, ORM-like solution.

I have tried the following:

posts = Post.objects.all().order_by('?')
first_group = posts[:5]
second_group = posts[5:]

But this will, sometimes, return the same posts in both groups.

I have also tried to trick the system doing the following:

posts = Post.objects.all().order_by('?')
first_group = posts[:5]
second_group = Post.objects.exclude(id__in=first_group)

But again no luck.

Can someone give me a few pointers so I don't have to loop over the records in pure Python?

To get unique posts, you can do:

posts = list(Post.objects.all().order_by('?')[:10])
first_group = posts[:5]
second_group = posts[5:]

This has the added advantage of making a single database query.

Referencing to Django Official Document ( https://docs.djangoproject.com/en/2.0/topics/db/queries/#querysets-are-lazy ), QuerySet is lazy.

This means QuerySet will not pass any queries to the DB until you have iterate the QuerySet.

So if you want to get query result to list, you must iterate the queryset first.

posts = Post.objects.all().order_by('?')
first_group = []
second_group = []

iterate_count = 0
for post in posts:
    if iterate_count < 5:
        first_group.append(post)
    elif iterate_count < 10:
        second_group.append(post)
    else:
        break

Maybe, above code will work fine.

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