# -*- coding: utf-8 -*- from operator import itemgetter from django.utils.translation import ugettext as _ def base_concrete_model(abstract, instance): """ Used in methods of abstract models to find the super-most concrete (non abstract) model in the inheritance chain that inherits from the given abstract model. This is so the methods in the abstract model can query data consistently across the correct concrete model. Consider the following:: class Abstract(models.Model) class Meta: abstract = True def concrete(self): return base_concrete_model(Abstract, self) class Super(Abstract): pass class Sub(Super): pass sub = Sub.objects.create() sub.concrete() # returns Super In actual Mezzanine usage, this allows methods in the ``Displayable`` and ``Orderable`` abstract models to access the ``Page`` instance when instances of custom content types, (eg: models that inherit from ``Page``) need to query the ``Page`` model to determine correct values for ``slug`` and ``_order`` which are only relevant in the context of the ``Page`` model and not the model of the custom content type. """ for cls in reversed(instance.__class__.__mro__): if issubclass(cls, abstract) and not cls._meta.abstract: return cls return instance.__class__ class EnumChoices(list): """ A helper to create constants from choices tuples. Usage: CONNECTION_CHOICES = EnumChoices( WIRED = (1, 'Wired connection'), WIRELESS = (2, 'Wi-fi or other generic wireless type'), MOBILE = (3, 'Mobile broadband'), ) It will then return a list with the passed tuples so you can use in the Django's fields choices option and, additionally, the returned object will have the constant names as attributes (eg. CONNECTION_CHOICES.MOBILE == 3). """ def __init__(self, **data): for item in sorted(data.items(), key=itemgetter(1)): self.append((item[1][0], item[1][1])) setattr(self, item[0], item[1][0])