Moved Node and View documentation from rst files to the source file.
[philo.git] / philo / models / collections.py
1 from django.contrib.contenttypes import generic
2 from django.contrib.contenttypes.models import ContentType
3 from django.db import models
4 from django.template import add_to_builtins as register_templatetags
5
6 from philo.models.base import value_content_type_limiter, register_value_model
7 from philo.utils import fattr
8
9
10 class Collection(models.Model):
11         """
12         Collections are curated ordered groupings of arbitrary models.
13         
14         """
15         #: :class:`CharField` with max_length 255
16         name = models.CharField(max_length=255)
17         #: Optional :class:`TextField`
18         description = models.TextField(blank=True, null=True)
19         
20         @fattr(short_description='Members')
21         def get_count(self):
22                 """Returns the number of items in the collection."""
23                 return self.members.count()
24         
25         def __unicode__(self):
26                 return self.name
27         
28         class Meta:
29                 app_label = 'philo'
30
31
32 class CollectionMemberManager(models.Manager):
33         use_for_related_fields = True
34
35         def with_model(self, model):
36                 """
37                 Given a model class or instance, returns a queryset of all instances of that model which have collection members in this manager's scope.
38                 
39                 Example::
40                 
41                         >>> from philo.models import Collection
42                         >>> from django.contrib.auth.models import User
43                         >>> collection = Collection.objects.get(name="Foo")
44                         >>> collection.members.all()
45                         [<CollectionMember: Foo - user1>, <CollectionMember: Foo - user2>, <CollectionMember: Foo - Spam & Eggs>]
46                         >>> collection.members.with_model(User)
47                         [<User: user1>, <User: user2>]
48                 
49                 """
50                 return model._default_manager.filter(pk__in=self.filter(member_content_type=ContentType.objects.get_for_model(model)).values_list('member_object_id', flat=True))
51
52
53 class CollectionMember(models.Model):
54         """
55         The collection member model represents a generic link from a :class:`Collection` to an arbitrary model instance with an attached order.
56         
57         """
58         #: A :class:`CollectionMemberManager` instance
59         objects = CollectionMemberManager()
60         #: :class:`ForeignKey` to a :class:`Collection` instance.
61         collection = models.ForeignKey(Collection, related_name='members')
62         #: The numerical index of the item within the collection (optional).
63         index = models.PositiveIntegerField(verbose_name='Index', help_text='This will determine the ordering of the item within the collection. (Optional)', null=True, blank=True)
64         member_content_type = models.ForeignKey(ContentType, limit_choices_to=value_content_type_limiter, verbose_name='Member type')
65         member_object_id = models.PositiveIntegerField(verbose_name='Member ID')
66         #: :class:`GenericForeignKey` to an arbitrary model instance.
67         member = generic.GenericForeignKey('member_content_type', 'member_object_id')
68         
69         def __unicode__(self):
70                 return u'%s - %s' % (self.collection, self.member)
71         
72         class Meta:
73                 app_label = 'philo'
74
75
76 register_templatetags('philo.templatetags.collections')
77 register_value_model(Collection)