Search code examples
djangodjango-annotate

how to annotate each object with random value


I want to have items with random annotations.

I tried this:

items = Item.objects.all().annotate(random_value=Value(randint(1,6)),output_field=PositiveIntegerField()))

And it is random, but THE SAME for EVERY Item in QuerySet.

But I want to have DIFFERENT value for EACH Item...

Any ideas?


Solution

  • According @Willem Van Onsem suggestion it is possible in Django<3.2:

    def my_view(request):
        from django.db.models.expressions import Func
        from django.db.models.functions.mixins import (
            FixDecimalInputMixin, NumericOutputFieldMixin,
        )
        class Random(NumericOutputFieldMixin, Func):
           function = 'RANDOM'
           arity = 0
    
           def as_mysql(self, compiler, connection, **extra_context):
               return super().as_sql(compiler, connection, function='RAND', **extra_context)
    
           def as_oracle(self, compiler, connection, **extra_context):
               return super().as_sql(compiler, connection, function='DBMS_RANDOM.VALUE', **extra_context)
    
           def as_sqlite(self, compiler, connection, **extra_context):
               return super().as_sql(compiler, connection, function='RAND', **extra_context)
    
           def get_group_by_cols(self, alias=None):
               return []
    
    
        items = Item.objects.all().annotate(random_value=Round(Random()*5+1))
    

    I did it inside def my_view, because if 3.2 becomes stable I remove this and add global from django.models.db import Round