annotate gcalendar/models.py @ 631:f36d1a168be7

For issue 27, disable login dialog button during POST. This seems to prevent multiple logins most of the time. You can still bang on the enter key and sometimes get more through.
author Brian Neal <bgneal@gmail.com>
date Wed, 14 Nov 2012 20:57:05 -0600
parents ee87ea74d46b
children 3e1905e523be
rev   line source
gremmie@1 1 """
gremmie@1 2 Models for the gcalendar application.
bgneal@456 3
gremmie@1 4 """
bgneal@458 5 import datetime
bgneal@458 6
gremmie@1 7 from django.db import models
gremmie@1 8 from django.db.models import Q
gremmie@1 9 from django.contrib.auth.models import User
bgneal@124 10
bgneal@128 11 from core.markup import site_markup
bgneal@228 12 import forums.tools
bgneal@458 13 from gcalendar.oauth import serialize_token, deserialize_token
gremmie@1 14
gremmie@1 15
bgneal@228 16 GIG_FORUM_SLUG = "gigs"
bgneal@228 17
gremmie@1 18 class PendingEventManager(models.Manager):
gremmie@1 19 """A manager for pending events."""
gremmie@1 20
gremmie@1 21 def get_query_set(self):
gremmie@1 22 """Returns a queryset of events that have been approved to update
gremmie@1 23 the Google calendar."""
gremmie@1 24 return super(PendingEventManager, self).get_query_set().filter(
bgneal@456 25 Q(status=Event.NEW_APRV) |
bgneal@456 26 Q(status=Event.EDIT_APRV) |
gremmie@1 27 Q(status=Event.DEL_APRV)
gremmie@1 28 )
gremmie@1 29
gremmie@1 30
gremmie@1 31 class Event(models.Model):
gremmie@1 32 """Model to represent calendar events."""
gremmie@1 33
gremmie@1 34 # Event status codes:
gremmie@1 35 (NEW, NEW_APRV, EDIT_REQ, EDIT_APRV, DEL_REQ, DEL_APRV, ON_CAL) = range(7)
gremmie@1 36
gremmie@1 37 STATUS_CHOICES = (
gremmie@1 38 (NEW, 'New'),
gremmie@1 39 (NEW_APRV, 'New Approved'),
gremmie@1 40 (EDIT_REQ, 'Edit Request'),
gremmie@1 41 (EDIT_APRV, 'Edit Approved'),
gremmie@1 42 (DEL_REQ, 'Delete Request'),
gremmie@1 43 (DEL_APRV, 'Delete Approved'),
gremmie@1 44 (ON_CAL, 'On Calendar'),
gremmie@1 45 )
gremmie@1 46
gremmie@1 47 user = models.ForeignKey(User)
gremmie@1 48 what = models.CharField(max_length=255)
gremmie@1 49 start_date = models.DateField()
gremmie@1 50 start_time = models.TimeField(null=True, blank=True)
gremmie@1 51 end_date = models.DateField()
gremmie@1 52 end_time = models.TimeField(null=True, blank=True)
gremmie@1 53 time_zone = models.CharField(max_length=64, blank=True)
gremmie@1 54 all_day = models.BooleanField(default=False)
gremmie@1 55 where = models.CharField(max_length=255, blank=True)
gremmie@1 56 description = models.TextField(blank=True)
gremmie@1 57 html = models.TextField(blank=True)
gremmie@1 58 date_submitted = models.DateTimeField(auto_now_add=True)
gremmie@1 59 google_id = models.CharField(max_length=255, blank=True)
bgneal@572 60 google_url = models.URLField(max_length=255, blank=True)
bgneal@228 61 status = models.SmallIntegerField(choices=STATUS_CHOICES, default=NEW,
bgneal@228 62 db_index=True)
bgneal@228 63 create_forum_thread = models.BooleanField(default=False)
gremmie@1 64
gremmie@1 65 objects = models.Manager()
gremmie@1 66 pending_events = PendingEventManager()
gremmie@1 67
gremmie@1 68 def __unicode__(self):
gremmie@1 69 return self.what
gremmie@1 70
gremmie@1 71 class Meta:
gremmie@1 72 ordering = ('-date_submitted', )
gremmie@1 73
gremmie@1 74 def save(self, *args, **kwargs):
bgneal@128 75 self.html = site_markup(self.description)
gremmie@1 76 super(Event, self).save(*args, **kwargs)
gremmie@1 77
bgneal@139 78 def is_approved(self):
bgneal@139 79 return self.status not in (self.NEW, self.EDIT_REQ, self.DEL_REQ)
bgneal@139 80 is_approved.boolean = True
gremmie@1 81
bgneal@228 82 def google_html(self):
bgneal@228 83 """Returns a HTML <a> tag to the event if it exits."""
bgneal@228 84 if self.google_url:
bgneal@228 85 return u'<a href="%s">On Google</a>' % self.google_url
bgneal@228 86 return u''
bgneal@228 87 google_html.allow_tags = True
bgneal@228 88 google_html.short_description = 'Google Link'
bgneal@228 89
bgneal@228 90 def notify_on_calendar(self):
bgneal@228 91 """
bgneal@228 92 This function should be called when the event has been added to the
bgneal@228 93 Google calendar for the first time. This gives us a chance to perform
bgneal@228 94 any first-time processing, like creating a forum thread.
bgneal@228 95 """
bgneal@228 96 if self.create_forum_thread:
bgneal@228 97 topic_name = '%s: %s' % (self.start_date.strftime('%m/%d/%Y'),
bgneal@228 98 self.what)
bgneal@228 99 post_body = "%s\n\n[Link to event on Google Calendar](%s)" % (
bgneal@228 100 self.description, self.google_url)
bgneal@228 101
bgneal@228 102 forums.tools.create_topic(
bgneal@228 103 forum_slug=GIG_FORUM_SLUG,
bgneal@456 104 user=self.user,
bgneal@228 105 topic_name=topic_name,
bgneal@228 106 post_body=post_body)
bgneal@228 107
bgneal@228 108 self.create_forum_thread = False
bgneal@228 109 self.save()
bgneal@456 110
bgneal@456 111
bgneal@458 112 class AccessTokenManager(models.Manager):
bgneal@458 113 """
bgneal@458 114 A manager for the AccessToken table. Only one access token is saved in the
bgneal@458 115 database. This manager provides a convenience method to either return that
bgneal@458 116 access token or a brand new one.
bgneal@458 117
bgneal@458 118 """
bgneal@458 119 def get_token(self):
bgneal@458 120 try:
bgneal@458 121 token = self.get(pk=1)
bgneal@458 122 except AccessToken.DoesNotExist:
bgneal@458 123 token = AccessToken()
bgneal@458 124
bgneal@458 125 return token
bgneal@458 126
bgneal@458 127
bgneal@456 128 class AccessToken(models.Model):
bgneal@456 129 """
bgneal@456 130 This model represents serialized OAuth access tokens for reading and
bgneal@456 131 updating the Google Calendar.
bgneal@456 132
bgneal@456 133 """
bgneal@456 134 auth_date = models.DateTimeField()
bgneal@456 135 token = models.TextField()
bgneal@456 136
bgneal@458 137 objects = AccessTokenManager()
bgneal@458 138
bgneal@456 139 def __unicode__(self):
bgneal@456 140 return u'Access token created on ' + unicode(self.auth_date)
bgneal@456 141
bgneal@458 142 def update(self, access_token, auth_date=None):
bgneal@458 143 """
bgneal@458 144 This function updates the AccessToken object with the input parameters:
bgneal@458 145 access_token - an access token from Google's OAuth dance
bgneal@458 146 auth_date - a datetime or None. If None, now() is used.
bgneal@458 147
bgneal@458 148 """
bgneal@458 149 self.auth_date = auth_date if auth_date else datetime.datetime.now()
bgneal@458 150 self.token = serialize_token(access_token)
bgneal@458 151
bgneal@458 152 def access_token(self):
bgneal@458 153 """
bgneal@458 154 This function returns a Google OAuth access token by deserializing the
bgneal@458 155 token field from the database.
bgneal@458 156 If the token attribute is empty, None is returned.
bgneal@458 157
bgneal@458 158 """
bgneal@458 159 return deserialize_token(self.token) if self.token else None