Skip to content

Instantly share code, notes, and snippets.

@manfre
Created January 6, 2014 15:45
Show Gist options
  • Save manfre/8284698 to your computer and use it in GitHub Desktop.
Save manfre/8284698 to your computer and use it in GitHub Desktop.
Django model manager that allows access and easy querying against read-only (computed) database fields.
class ComputedFieldsManager(models.Manager):
"""
Manager that can account for computed fields and fetch those fields, but
ensure they are not writeable.
Example usage:
objects = ComputedFieldsManager(computed_fields=['my_computed_field'])
objects = ComputedFieldsManager(computed_fields=[('my_computed_field', models.BooleanField())])
"""
use_for_related_fields = True
def __init__(self, *args, **kwargs):
computed_fields = kwargs.pop('computed_fields', [])
self.computed_fields = []
for f in computed_fields:
if isinstance(f, tuple):
name = f[0]
type = f[1]
else:
name = f
# no type specified, use arbitrarily long CharField
type = models.CharField(null=True, blank=True, max_length=200)
self.computed_fields.append((name, type))
super(ComputedFieldsManager, self).__init__(*args, **kwargs);
def get_query_set(self):
qs = super(ComputedFieldsManager, self).get_query_set()
if self.computed_fields:
qn = connection.ops.quote_name
table = qn(qs.model._meta.db_table)
qs = qs.extra(
select=dict([(x[0], '%s.%s' % (table, qn(x[0]))) \
for x in self.computed_fields]),
)
return qs
def computed_field_in(self, field, vals):
"""
Construct an extra clause of the pattern ``<table>.<field> IN (<vals>)``,
where table is the db_table name from the queryset's model.
"""
qn = connection.ops.quote_name
qs = self.get_query_set()
table = qn(qs.model._meta.db_table)
field = qn(field)
if isinstance(vals, basestring):
vals = [vals]
sql_where = u'{table}.{field} IN ({vals})'.format(
table=table,
field=field,
vals=(u'%s,' * len(vals)).rstrip(u','),
)
return qs.extra(
where=[sql_where],
params=vals,
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment