Django ORM: Filter by extra attribute

前端 未结 3 1235
既然无缘
既然无缘 2020-12-03 17:44

I want to filter some database objects by a concatenated string.

The normal SQL query would be:

SELECT concat(firstName, \' \', name) FROM person WHE         


        
3条回答
  •  無奈伤痛
    2020-12-03 18:22

    I solved this by implementing a custom Aggregate function. In this case I needed to concatenate individual fields into a street address to be able to filter/search for matches. The following aggregate function allows to specify a field and one or more others to perform a SQL CONCAT_WS.

    Edit 3 Aug 2015:

    A better implementation with details gleaned from https://stackoverflow.com/a/19529861/3230522. The previous implementation would fail if the queryset was used in a subquery. The table names are now correct, although I note that this just works for concatenation of columns from the same table.

    from django.db.models import Aggregate
    from django.db.models.sql.aggregates import Aggregate as SQLAggregate
    
    class SqlAggregate(SQLAggregate):
        sql_function = 'CONCAT_WS'
        sql_template = u'%(function)s(" ", %(field)s, %(columns_to_concatenate)s)'
    
        def as_sql(self, qn, connection):
            self.extra['columns_to_concatenate'] = ', '.join(
            ['.'.join([qn(self.col[0]), qn(c.strip())]) for c in self.extra['with_columns'].split(',')])
            return super(SqlAggregate, self).as_sql(qn, connection)
    
    class Concatenate(Aggregate):
        sql = SqlAggregate
    
        def __init__(self, expression, **extra):
            super(Concatenate, self).__init__(
                expression,
                **extra)
    
        def add_to_query(self, query, alias, col, source, is_summary):
    
            aggregate = self.sql(col,
                             source=source,
                             is_summary=is_summary,
                             **self.extra)
    
            query.aggregates[alias] = aggregate
    

提交回复
热议问题