views:

376

answers:

3

Is there a difference between filter and exclude in django? If I have

self.get_query_set().filter(modelField=x)

and I want to add another criteria, is there a meaningful difference between to following two lines of code?

self.get_query_set().filter(user__isnull=False, modelField=x)

self.get_query_set().filter(modelField=x).exclude(user__isnull=True)

is one considered better practice or are they the same in both function and performance?

+1  A: 

Both are lazily evaluated, so I would expect them to perform equivalently. The SQL is likely different, but with no real distinction.

Ned Batchelder
thanks. so it's just a matter of personal preference? i just wanted to make sure i wasn't going to do something inexplicably stupid.
Enrico
@Enrico: Not really, it depends on what you want. See my answer. Performance doesn't matter in this case, they are two methods that serve different purposes. For SQL generation, the documentation says about `.exclude()`: *Multiple parameters are joined via AND in the underlying SQL statement, and the whole thing is enclosed in a NOT().*
Felix Kling
@Felix. Thanks. I guess my main question - which I could have communicated more clearly was about the performance of both in django and then ultimately SQL. From your follow up comment, it sounds like one might perform better than the other but mostly based on the resulting SQL. However, changing the second statement to `.exclude(user__isnull=True).filter(modelField=x)` would then make the two statements more or less equal again.
Enrico
+4  A: 

In general exclude is opposite of filter. In this case both examples works the same.

Here:

self.get_query_set().filter(user__isnull=False, modelField=x)

You select entries that field user is not null and modelField has value x

In this case:

self.get_query_set().filter(modelField=x).exclude(user__isnull=True)

First you select entries that modelField has value x(both user in null and user is not null), then you exclude entries that have field user null.

I think that in this case it would be better use first option, it looks more cleaner. But both work the same.

Dominik Szopa
+1  A: 

It depends what you want to achieve. With boolean values it is easy to switch between .exclude() and .filter() but what about e.g. if you want to get all articles except those from March? You can write the query as

Posts.objects.exclude(date__month=3)

With .filter() it would be (but I not sure whether this actually works):

Posts.objects.filter(date__month__in=[1,2,4,5,6,7,8,9,10,11,12])

or you would have to use a Q object.

As the function name already suggest, .exclude() is used to exclude datasets from the resultset. For boolean values you can easily invert this and use .filter() instead, but for other values this can be more tricky.

Felix Kling