问题
I'm building dynamic filters which I pass by GET to a queryset filter:
for k, v in request.GET.iteritems():
kwargs[str(k)] = str(v)
students = models.Student.objects.filter( **kwargs )
and it's working for almost all the queries I'm throwing at it. However, I have a related model with a manytomany relationship, Group. So a student can be a member of many groups. I'm able to filter students who belong to a given group using the following:
'groups__in='+str(group.id)
e.g. - //example.com/students/?groups__in=1
But I can't figure out how to filter for students who don't belong to any group. I've tried the following without success:
groups__in=None # students == []
groups__exact=None # students == []
groups__iexact=None # FAIL not that I really expected this to work
groups__isnull=True # students == []
The last version was what I was hoping to have actually work. I'm sure I could get this to work by modifying the top code to something like
if request.GET['something']:
students = models.Student.objects.exclude(groups__isnull=False)
else:
students = models.Student.objects.filter( **kwargs )
So I guess the question becomes, how can i create
students = models.Student.objects.exclude(groups__isnull=False)
using .filter()?
回答1:
Maybe I don't understand the question. But I see:
list(MyMod.objects.exclude(foo__isnull=False)
) == list(MyMod.objects.filter(foo__isnull=True))
回答2:
I think models.Student.objects.filter(groups__isnull=True)
should do what you want. As skyl pointed out, this is the same as models.Student.objects.exclude(groups__isnull=False)
.
What's the problem with this solution? Could it be in your data? As a sanity check you could try
from django.db.models import Count
models.Student.objects.annotate(gcount=Count('groups').filter(gcount__gt=0)
which should yield the same results.
And:
If you take untrustworthy data from the client and feed them unchecked into your query, you should double check that you don't open a security hole that way (or that security is not a concern with your data).
回答3:
students = models.Student.objects.filter(groups=None)
Here is an example from some code i have lying around:
# add collaborator with no organizations
>>> john = Collaborator(first_name='John', last_name='Doe')
>>> john.save()
>>> john.organizations.all()
[]
# add another collaborator with no organizations
>>> jane = Collaborator(first_name='Jane', last_name='Doe')
>>> jane.save()
>>> jane.organizations.all()
[]
# filter for collaborators with no collaborators
>>> collabs_with_no_orgs = Collaborator.objects.filter(organizations=None)
>>> collabs_with_no_orgs
[<Collaborator: John Doe>, <Collaborator: Jane Doe>]
# add organization to collaborator
>>> jane.organizations = [Organization.objects.all()[0]]
>>> jane.save()
>>> jane.organizations.all()
[<Organization: organization 1>]
# filter for collaborators with no organizations
>>> collabs_with_no_orgs = Collaborator.objects.filter(organizations=None)
>>> collabs_with_no_orgs
[<Collaborator: John Doe>]
来源:https://stackoverflow.com/questions/5760419/django-queryset-filter-on-an-empty-list