Last active
August 29, 2015 14:22
-
-
Save bencharb/ef7044fe3d53fe3d74d3 to your computer and use it in GitHub Desktop.
Django ContentType Index
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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