Created
April 28, 2014 19:19
-
-
Save dzerrenner/11381487 to your computer and use it in GitHub Desktop.
Metaclass that adds couter methods for reverse foreign keys of Django models.
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
class ForeignCountMeta(ModelBase): | |
""" | |
Metaclass that adds couter methods for reverse foreign keys of Django models. | |
The methods that will be creates are defined in the models Meta options: | |
class CountedParent(models.Model, metaclass=ForeignCounterMeta): | |
class Meta: | |
counted_fields = { | |
"child1_count": {'relation_name': 'child1', 'short_description': 'Child 1 count'}, | |
"child2_count": {'relation_name': 'child2', 'short_description': 'Child 1 count'}, | |
} | |
class Child1(models.Model): | |
parent = ForeignKey(to=CountedParent) | |
class Child2(models.Model): | |
parent = ForeignKey(to=CountedParent) | |
With a CountedParent instance: | |
print(counted_parent.child1_count()) | |
print(counted_parent.child2_count()) | |
""" | |
def __init__(cls, name, bases, nmspc): | |
# check if the Meta options are available, not sure if this is necessary | |
if cls._meta and cls._meta.counted_fields: | |
def make_count(rel_name): | |
""" create a counter method for a specific relation """ | |
def _count(self): | |
# results in "return self.rel_name_set.count()" | |
return getattr(self, "%s_set" % rel_name).count() | |
return _count | |
# do it for all items in the counted_fields option | |
for method_name, args in cls._meta.counted_fields.items(): | |
# remove "relation_name" from the attributes, see further down | |
relation_name = args.pop('relation_name') | |
# create the counter method | |
count_method = make_count(relation_name) | |
# set the remaining attributes as attributes on the new method: | |
for attr, value in args.items(): | |
setattr(count_method, attr, value) | |
setattr(cls, method_name, count_method) | |
super(ForeignCountMeta, cls).__init__(name, bases, nmspc) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You have to add the counted_fields attribute to the Meta-Options in your settings.py: