Skip to content

Instantly share code, notes, and snippets.

@lostb1t
Last active May 17, 2017 14:03
Show Gist options
  • Save lostb1t/bf7562c400d0512094e0c4b83e1fa76b to your computer and use it in GitHub Desktop.
Save lostb1t/bf7562c400d0512094e0c4b83e1fa76b to your computer and use it in GitHub Desktop.
ModelCollector
class UserSalesCollector(ModelCollector):
fields = [
'uuid',
'date_joined',
'birthdate.year',
'zip4',
'userrecord.num_orders',
'userrecord.total_spent',
'userrecord.num_product_views',
'loyaltycard'
]
model_class = User
def get_queryset(self, start_date, end_date):
qs = super(UserSalesCollector, self).get_queryset(start_date, end_date)
return qs.select_related('userrecord').order_by('id')
"""
Callbacks
"""
def get_loyaltycard(self, item):
return 'JA' if item.loyaltycard else 'NEE'
def get_zip4(self, item, value):
address = item.addresses.filter(is_default_for_billing=True).last()
if address:
return address.postcode[:4]
return self.default_value
class ModelCollector(Collector):
"""
Collector for Django models.
fields:: List of fields to collect.
Either a string of the field name, ex:
fields = ['pk', 'name']
or a tuple with a custom label, ex:
fields = [('pk', 'Identifier'), name]
model_class:: Django model class
use_verbose_name:: Use the verbose name of the field for the header
"""
fields = []
model_class = None
use_verbose_name = True
def get_header(self):
header = []
for field in self.fields:
header.append(self._resolve_label(field, self.model_class))
return header
def get_item(self, obj):
item = []
for field in self.fields:
field_name, label = self._extract_field(field)
item.append(self._resolve_value(field_name, obj))
return item
def get_items(self, start_date, end_date):
items = []
for obj in self.get_queryset(start_date, end_date):
items.append(self.get_item(obj))
return items
def get_queryset(self, start_date, end_date):
return self.model_class.objects.all()
"""
Internals
"""
def _resolve_value(self, field_name, obj):
field_tree = field_name.split('.')
callback_function = "get_{}".format(('_').join(field_tree))
try:
return getattr(self, callback_function)(obj)
except:
value = self._resolve_value_from_field(field_name, obj)
return value
def _resolve_value_from_field(self, field_name, value):
field_tree = field_name.split('.')
for field_name in field_tree:
value = self._get_value(field_name, value)
return value
def _get_value(self, field_name, obj):
try:
value = getattr(obj, field_name)
except:
value = self.default_value
return value
def _resolve_label(self, field, model_class):
label = None
if self._is_list(field):
# custom label
label = list(field)[1]
elif self.use_verbose_name:
# resolve verbose name
label = self._resolve_verbose_name(field, model_class)
if not label:
label = field
return label
def _resolve_verbose_name(self, field, model_class):
verbose_name = None
field_tree = field.split('.')
l = len(field_tree)
i = 0
for field in field_tree:
i += 1
labell = self._get_verbose_name(field, model_class)
if labell:
verbose_name = labell
if i < l:
f = model_class._meta.get_field(field)
try:
model_class = f.related_model
labell = self._get_verbose_name(field_tree[i], model_class)
if labell:
verbose_name = labell
except:
pass
return verbose_name
def _get_verbose_name(self, field, model_class):
try:
label = model_class._meta.get_field(field).verbose_name
except:
label = None
return label
def _extract_field(self, field):
if self._is_list(field):
field_name, label = list(field)
else:
field_name = field
label = None
return field_name, label
def _is_list(self, field):
if isinstance(field, (list, tuple)):
return True
return False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment