Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@hellpanderrr
Last active January 26, 2016 13:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hellpanderrr/07a54cf8948b1a7f2f2f to your computer and use it in GitHub Desktop.
Save hellpanderrr/07a54cf8948b1a7f2f2f to your computer and use it in GitHub Desktop.
Django PostgreSQL string_agg
#models.py
from django.db.models import Aggregate
class Concat(Aggregate):
def add_to_query(self, query, alias, col, source, is_summary):
#we send source=CharField to prevent Django from casting string to int
aggregate = SQLConcat(col, source=models.CharField(), is_summary=is_summary, **self.extra)
query.aggregates[alias] = aggregate
def __init__(self, col, distinct=False, **extra):
super(Concat, self).__init__(col, distinct=(
distinct and 'DISTINCT ' or ''),
**extra)
#For PostgreSQL >= 9.0
from django.db.models.sql.aggregates import Aggregate as SQLAggregate
#Aways use with separator, e.g. .annotate(values=Concat('value', separator=','))
class SQLConcat(SQLAggregate):
sql_function = 'string_agg'
@property
def sql_template(self):
#the ::text cast is a hardcoded hack to work with integer columns
return "%(function)s(%(distinct)s(%(field)s), '%(separator)s')"
#Usage
from app_name.models import Concat
model_name.objects().all().values('field_1').annotate(distinct_concatenation=Concat('some_other_field',separator=',',distinct=True))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment