Reputation: 2550
Suppose I have a list of skills:
skills = ['Python', 'Django', 'Java']
Suppose I then perform
Freelancer.object.filter(Q(skills=skills[0]))
Both Freelancers have this skill but despite the query not being the entirety of their repertoire I still want them to appear, which they will. I perform:
Freelancer.object.filter(Q(skills=skills[0]) | Q(skills=skills[1]) | Q(skills=skills[3]))
Freelancer one has all three skills, so I want him to appear. Freelancer two only matches 2/3 so I don't want him to appear but he obviously will because of the query. How can I do this?
Suppose this is possible with Q
and skills
is a list of size n
. Is it possible to perform this query dynamically?
# models.py
class Freelancer(models.Model):
def __unicode__(self):
return self.first_name
user = models.OneToOneField(User)
first_name = models.CharField(max_length=128)
surname = models.CharField(max_length=128)
university = models.CharField(max_length=256)
biography = models.TextField(default="")
skills = models.ManyToManyField(Skill, blank=True)
profile_picture = models.ImageField(blank=True, upload_to='freelancer/images')
object = UserManager()
class Skill(models.Model):
skill = models.TextField(primary_key=True, max_length=128)
def __unicode__(self):
return self.skill
EDIT:
For clarity I've provided the POST part of the view
# views.py
form = FilterFreelancerForm(request.POST)
skills = request.POST.getlist('skills_select')
queries = [Q(skills=s) for s in skills]
freelancers = Freelancer.object.filter(*queries)
Upvotes: 2
Views: 57
Reputation: 61225
You need to use &
(AND) instead of |
(OR)
skills = ['Python', 'Django', 'Java']
queries = [Q(skill=s) for s in skills]
Freelancer.Object.filter(*queries)
or
Freelancer.Object.filter(Q(skills=skills[0]) & Q(skills=skills[1]) & Q(skills=skills[3]))
Upvotes: 1
Reputation: 3234
You need to call filter
multiple times, because inside one filter, there can be only one JOIN
to the Skills
table. Source: https://docs.djangoproject.com/en/1.8/topics/db/queries/#spanning-multi-valued-relationships
So why not try it this way:
freelancers = Freelancer.objects.all()
for skill in skills:
freelancers = freelancers.filter(skills__skill=skill)
print(list(freelancers))
Upvotes: 1