Skip to content

Instantly share code, notes, and snippets.

@bencharb
Last active August 29, 2015 14:22
Show Gist options
  • Save bencharb/ef7044fe3d53fe3d74d3 to your computer and use it in GitHub Desktop.
Save bencharb/ef7044fe3d53fe3d74d3 to your computer and use it in GitHub Desktop.
Django ContentType Index
#!/bin/python
#
class ContentTypeIndex(object):
"""
Get content type based on class name, model name, pk, etc
In [00]: get_content_type = ContentTypeIndex(ContentType.objects.all())
In [01]: get_content_type('database')
Out[01]: <ContentType: database>
In [02]: get_content_type(Database)
Out[02]: <ContentType: database>
In [03]: get_content_type('web site')
Out[03]: <ContentType: website>
"""
def __init__(self, ct_queryset):
super(ContentTypeIndex, self).__init__()
self.index = {}
self.apps = collections.defaultdict(dict)
for ct in ct_queryset:
self.set_indexes(ct)
def set_indexes(self, ct):
pk, app_label = ct.pk, ct.app_label
self.index[pk] = ct
for attr in 'model', 'name':
if attr not in self.apps[app_label]:
self.apps[app_label][attr] = {}
self.apps[app_label][attr][getattr(ct, attr)] = pk
if 'model__name__' not in self.apps[app_label]:
self.apps[app_label]['model__name__'] = {}
model_class = ct.model_class()
if model_class is not None:
self.apps[app_label]['model__name__'][ct.model_class().__name__] = pk
def strategy_queryset(self, obj):
return obj.model.__name__
def strategy_model(self, obj):
return obj.__name__
def strategy_instance(self, obj):
return obj.__class__.__name__
def strategy_ct_value(self, obj):
return obj
@property
def strategies(self):
return (self.strategy_model,
self.strategy_queryset,
self.strategy_instance,
self.strategy_ct_value,)
def interrogate_pk(self, obj, app_label):
if isinstance(obj, int):
try:
return self.index[obj]
except KeyError:
return
result = None
for strategy in self.strategies:
try:
test_val = strategy(obj)
except AttributeError:
continue
for attr, attr_index in self.apps[app_label].iteritems():
if test_val in attr_index:
result = attr_index[test_val]
break
else:
result = None
if result is not None:
break
return result
def get_content_type(self, obj, app_label):
pk = self.interrogate_pk(obj, app_label)
if pk is not None:
return self.index[pk]
def __call__(self, obj, app_label=None):
if app_label is not None:
return self.get_content_type(obj, app_label)
else:
for app_label in self.apps:
ct = self.get_content_type(obj, app_label)
if ct is not None:
return ct
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment