Skip to content

Instantly share code, notes, and snippets.

@spookylukey
Last active November 14, 2020 10:42
Show Gist options
  • Save spookylukey/33afaa72edbb8d436fea45182aae49bc to your computer and use it in GitHub Desktop.
Save spookylukey/33afaa72edbb8d436fea45182aae49bc to your computer and use it in GitHub Desktop.
Visidata 1.x glue code for Django models and attrs, with type support
from datetime import date
import visidata
from django.db.models import QuerySet
def get_main_attrs(instance):
if hasattr(instance, '_meta'):
return meta_to_col_list(instance._meta)
elif hasattr(instance, '__attrs_attrs__'):
return [(field.name, field.type or visidata.anytype)
for field in instance.__attrs_attrs__]
return []
def meta_to_col_list(_meta):
retval = []
for field in _meta.get_fields():
if not hasattr(field, 'get_attname'):
continue
if getattr(field, 'many_to_many', False):
continue
retval.append((field.get_attname(), django_to_vd_type(field)))
return retval
def django_to_vd_type(field):
return {
'AutoField': int,
'BigAutoField': int,
'BigIntegerField': int,
'BooleanField': int,
'DateField': date,
'DecimalField': float,
'FloatField': float,
'ForeignKey': int, # good enough for now...
'PositiveIntegerField': int,
'PositiveSmallIntegerField': int,
'SmallIntegerField': int,
'CharField': str,
'TextField': str,
}.get(field.get_internal_type(), visidata.anytype)
class QuerySetSheet(visidata.Sheet):
@visidata.asyncthread
def reload(self):
self.rows = []
self.columns = [
visidata.ColumnAttr(name, type=t)
for name, t in meta_to_col_list(self.source.model._meta)
]
for item in visidata.Progress(self.source.iterator(), total=self.source.count()):
self.rows.append(item)
class AutoSheet(visidata.Sheet):
def reload(self):
self.rows = self.source
if len(self.rows) == 0:
self.columns = []
else:
self.columns = [visidata.ColumnAttr(name, type=t)
for name, t in get_main_attrs(self.rows[0])
]
def vd(objects):
"""
Wrapper around visidata.run with custom sheet types
"""
sheet = None
if isinstance(objects, QuerySet):
sheet = QuerySetSheet(objects.model.__name__, source=objects)
elif isinstance(objects, list) and len(objects) > 0:
instance = objects[0]
if hasattr(instance, '_meta') or hasattr(instance, '__attrs_attrs__'):
sheet = AutoSheet(instance.__class__.__name__, source=objects)
if sheet is None:
sheet = visidata.load_pyobj('', objects)
return visidata.run(sheet)
@spookylukey
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment