Question

I am trying to get a random list of objects and use that as a queryset for a form field. But since its a list and not a queryset this won't work. A friend advised to use a manager for this. but now i am not quite sure where to start.

My function to get the "queryset" list:

def get_job_list():
    all_jobs = ShortJob.objects.exclude(rarity__exact=0)
    always = ShortJob.objects.filter(rarity=0)
    pick_list = []
    job_list = []

    for job in all_jobs:
        pick_list.extend([job] * job.rarity)

    counter = 0
    while counter < 5:
        counter += 1
        job = choice(pick_list)
        job_list.append(job)

        while job in pick_list:
            pick_list.remove(job)

    for job in always:
        job_list.append(job)

    return job_list

and my form:

class ShortJobForm(forms.Form):

    options = forms.ModelChoiceField(queryset=ShortJob.get_job_list, widget=forms.RadioSelect)

Can someone please point me in the right direction to tackle this problem

my try so far at rewriting the function into a manager:

class ShortJobManager(models.Manager):
""" create a random short job queryset"""

    def get_queryset(self):
        all_jobs = ShortJob.objects.exclude(rarity__exact=0)
        always = ShortJob.objects.filter(rarity=0)
        pick_list = []
        job_list = []

        for job in all_jobs:
            pick_list.extend([job] * job.rarity)

        counter = 0
        while counter < 5:
            counter += 1
            job = choice(pick_list)
            job_list.append(job)

            while job in pick_list:
                pick_list.remove(job)

        for job in always:
            job_list.append(job)

        return super(ShortJobManager, self).get_queryset(job_list)
Was it helpful?

Solution

You can change your get_job_list() function like so, so that it returns a queryset:

def get_job_list():
    all_jobs = ShortJob.objects.exclude(rarity__exact=0)
    always = ShortJob.objects.filter(rarity=0)
    pick_list = []
    pk_list = []

    for job in all_jobs:
        pick_list.extend([job.pk] * job.rarity)  # list of pks

    counter = 0
    while counter < 5:
        counter += 1
        job_pk = choice(pick_list)
        pk_list.append(job_pk)

        while job_pk in pick_list:
            pick_list.remove(job_pk)

    # pk_list is now a list of pks you can filter on
    return always.filter(pk__in=pk_list)

Something roughly like that. I tried to maintain the purpose of your function, but may have misunderstood it in some places. Main point being:

You can pick random pks and then filter on them in order to get a queryset.

OTHER TIPS

I suggest you may use raw qs contains UNION section. Something like this:

 ShortJob.objects.raw('SELECT * FROM myapp_shortjob WHERE rarity=0 UNION SELECT * FROM myapp_shortjob WHERE rarity!=0 ORDER BY random()')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top