Skip to content

Instantly share code, notes, and snippets.

@rfong
Last active February 22, 2017 19:27
Show Gist options
  • Save rfong/26453b6eec24a2a55f68 to your computer and use it in GitHub Desktop.
Save rfong/26453b6eec24a2a55f68 to your computer and use it in GitHub Desktop.
useful django queryset mixins. import in settings to use.
from django.db import models
from django.db.models.query import QuerySet
class QuerySetExplainMixin:
"""
Dump SQL EXPLAIN for a Queryset.
Usage: `queryset.explain()`
"""
def explain(self, analyze=False, verbose=False):
from django.db import connections
cursor = connections[self.db].cursor()
cmd = 'explain'
cmd += ' analyze' if analyze else ''
cmd += ' verbose' if verbose else ''
cursor.execute('%s %s' % (cmd, str(self.query)))
return cursor.fetchall()
class QuerySetFieldValuesMixin:
"""
Returns generator of values for one field on a Queryset.
Usage: `queryset.field_values('name')`
"""
def field_values(self, field_name, distinct=False):
values = self.values(field_name)
if distinct:
values = values.distinct()
return (row[field_name] for row in values)
class QuerySetCountGroupbyMixin:
"""
Useful for debugging in shell.
Return a COUNT(*) GROUP BY breakdown of queryset by a specified attribute,
i.e. a sorted (descending) list of dictionaries {attr value: count} of each
represented attribute.
By default, print human readable breakdown.
Usage: `queryset.count_groupby('group_id')`
"""
def count_groupby(self, attr, silent=False):
counts = (self.values(attr).annotate(count=models.Count(attr))
.order_by('count').reverse())
choices = dict(getattr(self.model._meta.get_field(attr), 'choices', []))
if not silent and choices.keys():
for group in counts:
print group['count'], '\t', choices.get(group[attr])
return counts
QuerySet.__bases__ += (QuerySetExplainMixin, QuerySetFieldValuesMixin,
QuerySetCountGroupbyMixin)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment