Moved a few more miscellaneous things into master from embed that did not belong...
[philo.git] / utils.py
1 from django.db import models
2 from django.contrib.contenttypes.models import ContentType
3 from django.core.paginator import Paginator, EmptyPage
4
5
6 class ContentTypeLimiter(object):
7         def q_object(self):
8                 return models.Q(pk__in=[])
9         
10         def add_to_query(self, query, *args, **kwargs):
11                 query.add_q(self.q_object(), *args, **kwargs)
12
13
14 class ContentTypeRegistryLimiter(ContentTypeLimiter):
15         def __init__(self):
16                 self.classes = []
17         
18         def register_class(self, cls):
19                 self.classes.append(cls)
20         
21         def unregister_class(self, cls):
22                 self.classes.remove(cls)
23         
24         def q_object(self):
25                 contenttype_pks = []
26                 for cls in self.classes:
27                         try:
28                                 if issubclass(cls, models.Model):
29                                         if not cls._meta.abstract:
30                                                 contenttype = ContentType.objects.get_for_model(cls)
31                                                 contenttype_pks.append(contenttype.pk)
32                         except:
33                                 pass
34                 return models.Q(pk__in=contenttype_pks)
35
36
37 class ContentTypeSubclassLimiter(ContentTypeLimiter):
38         def __init__(self, cls, inclusive=False):
39                 self.cls = cls
40                 self.inclusive = inclusive
41         
42         def q_object(self):
43                 contenttype_pks = []
44                 def handle_subclasses(cls):
45                         for subclass in cls.__subclasses__():
46                                 try:
47                                         if issubclass(subclass, models.Model):
48                                                 if not subclass._meta.abstract:
49                                                         if not self.inclusive and subclass is self.cls:
50                                                                 continue
51                                                         contenttype = ContentType.objects.get_for_model(subclass)
52                                                         contenttype_pks.append(contenttype.pk)
53                                         handle_subclasses(subclass)
54                                 except:
55                                         pass
56                 handle_subclasses(self.cls)
57                 return models.Q(pk__in=contenttype_pks)
58
59
60 def fattr(*args, **kwargs):
61         def wrapper(function):
62                 for key in kwargs:
63                         setattr(function, key, kwargs[key])
64                 return function
65         return wrapper
66
67
68 def paginate(objects, per_page=None, page_number=1):
69         """
70         Given a list of objects, return a (paginator, page, objects) tuple.
71         """
72         try:
73                 per_page = int(per_page)
74         except (TypeError, ValueError):
75                 # Then either it wasn't set or it was set to an invalid value
76                 paginator = page = None
77         else:
78                 # There also shouldn't be pagination if the list is too short. Try count()
79                 # first - good chance it's a queryset, where count is more efficient.
80                 try:
81                         if objects.count() <= per_page:
82                                 paginator = page = None
83                 except AttributeError:
84                         if len(objects) <= per_page:
85                                 paginator = page = None
86         
87         try:
88                 return paginator, page, objects
89         except NameError:
90                 pass
91         
92         paginator = Paginator(objects, per_page)
93         try:
94                 page_number = int(page_number)
95         except:
96                 page_number = 1
97         
98         try:
99                 page = paginator.page(page_number)
100         except EmptyPage:
101                 page = None
102         else:
103                 objects = page.object_list
104         
105         return paginator, page, objects