Lookups
Book.objects.filter(title__glob='Django*')
Book.objects.filter(title__lower__glob='*DJanGo*')
Book.objects.annotate(
author_str=GroupConcat('authors__name')
)
Why not extra() ?
Lookup Class
Create a custom lookup
Demo - Glob Lookup
@models.CharField.register_lookup
class GlobLookup(models.Lookup):
lookup_name = 'glob'
def as_sql(self, compiler, connection):
lhs_sql, lhs_params = self.process_lhs(compiler, connection)
rhs_sql, rhs_params = self.process_rhs(compiler, connection)
return "%s glob %s" % (lhs_sql, rhs_sql), lhs_params + rhs_params
Book.objects.filter(title__glob="*Django*")
Transform - case insensitive
Transform takes in a value, outputs a transformed value
# note it *is* register_lookup
@models.CharField.register_lookup
class LowerTransform(models.Transform):
lookup_name = 'lower'
def as_sql(self, compiler, connection):
lhs_sql, lhs_params = compiler.compile(self.lhs)
return 'lower(%s)' % lhs_sql, lhs_params
Book.objects.filter(title__lower__glob="*django*")
Expressions
Create expression in 1.8
# note it *is* register_lookup
class GroupConcat(models.Aggregate):
function = 'group_concat'
Book.objects.all().annotate(
authors_str=GroupConcat('author__name')
)
# combine various things - produces complex SQL query
Book.objects.all().annotate(
authors_str=GroupConcat('author__name')
).filter(
authors_str__lower__glob="*a,m*"
)
New in Django 1.8
all expressions support arithmetic operations
all aggregates are expressions
annotate price_pre_page = Sum ‘books__price’ / Sum ‘books__pages’
output_field
annotate(
name_len=Length('name')
).filter(name_len__gte(10))
Multiple SQL dialects
Hstore and ArrayField
Dog.objects.create(
name='Ruth',
data={'breed': 'labrador', ...}
)
Dog.objects.filter(data__breed='labrador')
Dog.objects.filter(data__breed__icontains='l')
ArrayField
Post.objects.create(
name='first post',
tags=['thoughts', 'django']
)
filter(tags__contains=['thoughts', 'django'])
filter(tags__overlap=['thoughts', 'django'])
filter(tags__1__lower__glob='*o*')
Next
Much more in Django docs