Comment

Peter Bengtsson

I didn't know about the __isnull trick. Thanks for that.

No, putting completed=True/False in a Q-object does work as long as it's using my manager (MyModel.objects). That was the whole point of the blog :)

Parent comment

Andreas Pelme

Why don't you just use MyModel.objects.filter(completed_date__isnull=True) instead? It might be slightly less convenient to write when making queries, but you wont need to create a custom manager. Putting completed=True/False in a Q-object will not work either.

Replies

Andreas Pelme

I think that you are missing my point with Q-objects. Your manager only rewrites kwargs passed to filter and exclude, it will not rewrite Q objects that are passed in directly. With Q objects i mean django.db.models.Q: http://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects

If you had another field - foo - on MyModel and wanted all objects that are completed or where foo='bar', you would issue a query that looks something like this:

MyModel.objects.filter(Q(completed=True) | Q(foo='bar'))

You cannot use your rewrite when chaining filters(), since your filter()/exclude() overrides only works on the manager, and not the queryset. This means that MyModel.objects.all().filter(completed=True) will not work either.

I would just use __isnull instead, it does exactly what you want, without going through the hassle of overriding managers, querys and Q objects - and works everywhere.

However, I think your post is interesting and shows some of the potential with being able to subclass and override managers. It is definately a violation of DRY and ugly to have different fields.

Peter Bengtsson

I seeeeeee! When you wrote Q-object I first thought you meant Queryset, not the search thingy.

And now I see what you mean about MyModel.objects.all().filter(completed=True).

I guess I've taken on a principle too strongly that doesn't quite work the Django way.