Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django search multiple filters

Lets say I have a model

models.py

class user:
    name = models.CharField(max_length=25)

class job:
    job_name = models.CharField(max_length=25)

class user_job:
    user = models.ForeignKey('user')
    job  = models.ForeignKey('job')

forms.py

 jobs = (
     ('0', 'a'),
     ('1', 'b'),
     ('2', 'c'),
 )

 class searchForm:
     box = forms.ModelMultipleChoiceField(
                                          choices = jobs,
                                          widget  = forms.CheckboxSelectMultiple(),
                                          label   = 'Search',
                                         )

I can search for users that have job 'a' with

user_job.objects.filter(job__exact = 'a') ...

I tried to search for users that have both job 'a' and job 'c' like so

search_q = user_job.objects.filter(job__exact = 'a')
search_q = search_q.filter(job__exact = 'c')

but I get all users that have job 'a' or job 'c', and I need all users that have both jobs.

Is there a way I can filter it through Django, or do I need to filter on one job and then iterate through the results and check for the 2nd job?

like image 893
void Avatar asked Dec 15 '10 13:12

void


People also ask

Can we use multiple filters in Django?

The filter() method takes the arguments as **kwargs (keyword arguments), so you can filter on more than one field by sepearting them by a comma.

What are QuerySets in django?

A QuerySet is a collection of data from a database. A QuerySet is built up as a list of objects. QuerySets makes it easier to get the data you actually need, by allowing you to filter and order the data.

How to store data in django models?

Creating objectsTo create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database. This performs an INSERT SQL statement behind the scenes. Django doesn't hit the database until you explicitly call save() . The save() method has no return value.

What is Django filter?

Django-filter is a generic, reusable application to alleviate writing some of the more mundane bits of view code. Specifically, it allows users to filter down a queryset based on a model's fields, displaying the form to let them do this.


1 Answers

You'll probably find it easier to search from the User model since what you want is a list of Userss who have both jobs. Django automatically sets up properties on your models that allow you to access related models both from model instances and in DB queries.

Assuming you set up your models like so:

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=25)

    def __repr__(self):
        return '<User: %s>' % self.name

class Job(models.Model):
    name = models.CharField(max_length=25)

    def __repr__(self):
        return '<Job: %s>' % self.name

class UserJob(models.Model):
    user = models.ForeignKey(User)
    job = models.ForeignKey(Job)

    def __repr__(self):
        return '<UserJob: %s %s>' % (self.user.name, self.job.name)

And populate it as follows:

u1 = User.objects.create(name='u1')
u2 = User.objects.create(name='u2')
u3 = User.objects.create(name='u3')

a = Job.objects.create(name='a')
b = Job.objects.create(name='b')
c = Job.objects.create(name='c')

UserJob.objects.create(user=u1, job=a)
UserJob.objects.create(user=u2, job=a)
UserJob.objects.create(user=u2, job=b)
UserJob.objects.create(user=u3, job=a)
UserJob.objects.create(user=u3, job=c)

The following query will return you user 3, which is the only user who has both "Job a" and "Job c":

u = User.objects.filter(userjob__job=a).filter(userjob__job=c)

(or, if you prefer to refer to the jobs by name rather than Job instance):

u = User.objects.filter(userjob__job__name='a').filter(userjob__job__name='c')

You can see how Django is allowing you to traverse the related fields from the User model to the UserJob model with the double underscore notation (the Django docs on this are here: http://docs.djangoproject.com/en/1.2/topics/db/queries/#lookups-that-span-relationships.

Once you get the User object back, you can similarly access the UserJob instances using the relationship properties that Django adds to the model:

u = User.objects.filter(userjob__job__name='a').filter(userjob__job__name='c')
jobs = u.userjob_set.all()
like image 133
Jarret Hardie Avatar answered Oct 17 '22 00:10

Jarret Hardie