Removed location models and subclass limiting in favor of a ContentTypeRegistryLimite...
[philo.git] / contrib / julian / models.py
1 from django.conf import settings
2 from django.contrib.contenttypes.generic import GenericForeignKey
3 from django.contrib.contenttypes.models import ContentType
4 from django.core.exceptions import ValidationError
5 from django.core.validators import RegexValidator
6 from django.db import models
7 from philo.models.base import Tag, Entity
8 from philo.models.fields import TemplateField
9 from philo.utils import ContentTypeRegistryLimiter
10 import re
11
12
13 # TODO: Could this regex more closely match the Formal Public Identifier spec?
14 # http://xml.coverpages.org/tauber-fpi.html
15 FPI_REGEX = re.compile(r"(|\+//|-//)[^/]+//[^/]+//[A-Z]{2}")
16
17
18 location_content_type_limiter = ContentTypeRegistryLimiter()
19
20
21 def register_location_model(model):
22         location_content_type_limiter.register_class(model)
23
24
25 def unregister_location_model(model):
26         location_content_type_limiter.unregister_class(model)
27
28
29 class Location(Entity):
30         name = models.CharField(max_length=255)
31         
32         def __unicode__(self):
33                 return self.name
34
35
36 register_location_model(Location)
37
38
39 class TimedModel(models.Model):
40         start_date = models.DateField(help_text="YYYY-MM-DD")
41         start_time = models.TimeField(blank=True, null=True, help_text="HH:MM:SS - 24 hour clock")
42         end_date = models.DateField()
43         end_time = models.TimeField(blank=True, null=True)
44         
45         def is_all_day(self):
46                 return self.start_time is None and self.end_time is None
47         
48         def clean(self):
49                 if bool(self.start_time) != bool(self.end_time):
50                         raise ValidationError("A %s must have either a start time and an end time or neither.")
51                 
52                 if self.start_date > self.end_date or self.start_date == self.end_date and self.start_time > self.end_time:
53                         raise ValidationError("A %s cannot end before it starts." % self.__class__.__name__)
54         
55         class Meta:
56                 abstract = True
57
58
59 class Event(Entity, TimedModel):
60         name = models.CharField(max_length=255)
61         slug = models.SlugField(max_length=255)
62         
63         location_content_type = models.ForeignKey(ContentType, limit_choices_to=location_content_type_limiter)
64         location_pk = models.TextField()
65         location = GenericForeignKey('location_content_type', 'location_pk')
66         
67         description = TemplateField()
68         
69         tags = models.ManyToManyField(Tag, blank=True, null=True)
70         
71         parent_event = models.ForeignKey('self', blank=True, null=True)
72         
73         owner = models.ForeignKey(getattr(settings, 'PHILO_PERSON_MODULE', 'auth.User'))
74         
75         # TODO: Add uid - use as pk?
76
77
78 class Calendar(Entity):
79         name = models.CharField(max_length=100)
80         #slug = models.SlugField(max_length=255, unique=True)
81         events = models.ManyToManyField(Event, related_name='calendars')
82         
83         # TODO: Can we auto-generate this on save based on site id and calendar name and settings language?
84         uuid = models.CharField("Calendar UUID", max_length=100, unique=True, help_text="Should conform to Formal Public Identifier format. See <http://en.wikipedia.org/wiki/Formal_Public_Identifier>", validators=[RegexValidator(FPI_REGEX)])