[Fixed]-Modulo in django queryset?


I don’t have Django 1.8 at hand to test it, but looks like you can do this using F with annotation, like this:

Foo.objects.annotate(idmod4=F('id') % 4).filter(idmod4=0)

(Django 1.7 and earlier doesn’t support using F in annotate)

For Django 1.7 and earlier you can always use .extra() but it isn’t very pretty:

Foo.objects.extra(where=["id %% %s = 0"], params=[4])


def as_sql(self, compiler, connection):
    lhs, params = compiler.compile(self.lhs)
    return "%s %% 4 = 0" % lhs, params

In Django 4 which I the following line:

return "%s %% 4 = 0" % lhs, params

should be as following:

return "%s %%%% 4 = 0" % lhs, params

Because %%%% the string will be interpolated twice once in as_mysql and other in db cursor so for sql statement %%%% become % which is the modulus operation.
This behavior is the same in most of Django classes that offer functionality to create a custom SQL template.

Leave a comment