Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modulo in django queryset?

Tags:

django

Is there already a way to select objects according to id % 4 == 0 in django queryset ?

The only solution I found so far is to write a custom Transform since modulo seems to be supported in Postgresql but I got errors.

Here is my code:

from django.db.models import Lookup, Transform
from django.db.models.fields import Field, IntegerField, AutoField

class Modulo4(Transform):
    lookup_name = 'modulo4'

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

AutoField.register_lookup(Modulo4)

foos = Foo.filter(id__modulo4=0)

And I get an error when the queryset is evaluated (with foos.count() or whatever):

IndexError: tuple index out of range

refering to a django file. It seems to be due to the modulo since I manage to make the custom transform work with the doc example.

Any idea on how to achieve this ?

like image 430
stellasia Avatar asked May 18 '15 15:05

stellasia


People also ask

What is F in Django QuerySet?

In the Django QuerySet API, F() expressions are used to refer to model field values directly in the database.

What is Q expression in Django?

Q object encapsulates a SQL expression in a Python object that can be used in database-related operations. Using Q objects we can make complex queries with less and simple code. For example, this Q object filters whether the question starts wiht 'what': from django.

How do you annotate in Django?

Appending the annotate() clause onto a QuerySet lets you add an attribute to each item in the QuerySet, like if you wanted to count the amount of articles in each category. However, sometimes you only want to count objects that match a certain condition, for example only counting articles that are published.

What is aggregate Django?

When specifying the field to be aggregated in an aggregate function, Django will allow you to use the same double underscore notation that is used when referring to related fields in filters. Django will then handle any table joins that are required to retrieve and aggregate the related value.


1 Answers

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])
like image 110
Spc_555 Avatar answered Oct 09 '22 07:10

Spc_555