Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

240
Visualizações
how to cast the output of Count() in django to FloatField in django 1.8

I am using django 1.8.

I have two models:-

class Query(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    title = models.TextField()
    details = models.TextField()
    pub_date = models.DateTimeField('date published')
    post_score=models.FloatField(default=0.0)
    ....

class Tags(models.Model):
    """docstring for Tags"""
    tagname=models.TextField()
grouppostlist=models.ManyToManyField(Query,through='GroupPostsTag',through_fields=('tag','query'))

# and another model(it stores tags for a query)

class GroupPostsTag(models.Model):
    query=models.ForeignKey('Query')
    tag=models.models.ForeignKey('Tags')

Now I want to sort queries based on the sum of "number of tags" and query's "post_score". I am looking for something like this:-

tagged_user_posts = Query.objects.filter(Q(tags__id__in=tags_list)).annotate(num_tags=Cast(Count('tags'),models.FloatField())).annotate(post_scores=F('num_tags')+F('post_score')).order_by('-post_scores')

Cast is provided in django 1.10. So what alternative I can use?

about 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

As I said in my comment that you can simply copy the source code of Cast class and save it in your projects and use it.

Turns out it wasn't as simple as that. You will also need to change the Cast.as_sql as it is in v1.10. And, no need to make a super call to Func.as_sql.

Just copy the following code and save it in your project. I've tested it and it works.

from django.db.models import Func, fields


class Cast(Func):
    """
    Coerce an expression to a new field type.
    """
    function = 'CAST'
    template = '%(function)s(%(expressions)s AS %(db_type)s)'

    mysql_types = {
        fields.CharField: 'char',
        fields.IntegerField: 'signed integer',
        fields.FloatField: 'signed',
    }

    def __init__(self, expression, output_field):
        super(Cast, self).__init__(expression, output_field=output_field)

    def as_sql(self, compiler, connection, function=None, template=None, arg_joiner=None, **extra_context):
        if 'db_type' not in extra_context:
            extra_context['db_type'] = self._output_field.db_type(connection)
        connection.ops.check_expression_support(self)
        sql_parts = []
        params = []
        for arg in self.source_expressions:
            arg_sql, arg_params = compiler.compile(arg)
            sql_parts.append(arg_sql)
            params.extend(arg_params)
        data = self.extra.copy()
        data.update(**extra_context)
        # Use the first supplied value in this order: the parameter to this
        # method, a value supplied in __init__()'s **extra (the value in
        # `data`), or the value defined on the class.
        if function is not None:
            data['function'] = function
        else:
            data.setdefault('function', self.function)
        template = template or data.get('template', self.template)
        arg_joiner = arg_joiner or data.get('arg_joiner', self.arg_joiner)
        data['expressions'] = data['field'] = arg_joiner.join(sql_parts)
        return template % data, params


    def as_mysql(self, compiler, connection):
        extra_context = {}
        output_field_class = type(self._output_field)
        if output_field_class in self.mysql_types:
            extra_context['db_type'] = self.mysql_types[output_field_class]
        return self.as_sql(compiler, connection, **extra_context)

    def as_postgresql(self, compiler, connection):
        # CAST would be valid too, but the :: shortcut syntax is more readable.
        return self.as_sql(compiler, connection, template='%(expressions)s::%(db_type)s')
about 4 years ago · Santiago Trujillo Relatório

0

As you mentioned in question for django 1.10 you can use built-in Cast function. For older versions you can use Func() expression

from django.db.models import Count, Func, F, ExpressionWrapper, FloatField
tagged_user_posts = Query.objects.filter(Q(tags__id__in=tags_list)).
    annotate(num_tags=Func(Count('tags'), 
                           template='%(function)s(%(expressions)s AS %(type)s)', 
                           function='Cast', 
                           type='float')
    ).
    annotate(post_scores=ExpressionWrapper(F('num_tags')+F('post_score'), output_field=FloatField())).
    order_by('-post_scores')
about 4 years ago · Santiago Trujillo Relatório

0

You could define Cast as

def Cast(what, as_type):
    if isinstance(as_type, Field):
        as_type = as_type.db_type(connection)
    return Func(
        what,
        template='%(function)s(%(expressions)s AS %(type)s)',
        function='Cast',
        type=as_type,
    )
about 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda