Files
@ b50974263c36
Branch filter:
Location: symposion_app/symposion/proposals/models.py - annotation
b50974263c36
5.6 KiB
text/x-python
i18n sponsor fields
Feedback from PyConJP development
```
commit 5973e32ebdc231b209b5c058664e8b2b4a1dbc54
Author: MURAOKA Yusuke <yusuke@jbking.org>
Date: Mon Mar 31 15:35:40 2014 +0900
introduce Benefit.content_type which is used to display localized
text
```
Signed-off-by: Hiroshi Miura <miurahr@linux.com>
Feedback from PyConJP development
```
commit 5973e32ebdc231b209b5c058664e8b2b4a1dbc54
Author: MURAOKA Yusuke <yusuke@jbking.org>
Date: Mon Mar 31 15:35:40 2014 +0900
introduce Benefit.content_type which is used to display localized
text
```
Signed-off-by: Hiroshi Miura <miurahr@linux.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 63d07f8db31c 5c07d3e9454b 7596922f4d68 7596922f4d68 464d85b36a64 7596922f4d68 6cf7a62da1cb 6cf7a62da1cb 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 5f311ca7bd4e 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 7b4c5cd205b5 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 5c07d3e9454b 5c07d3e9454b 7596922f4d68 7596922f4d68 36ab6d599ffc e00b646f20bf e00b646f20bf e00b646f20bf 5c07d3e9454b e00b646f20bf 5c07d3e9454b e00b646f20bf e00b646f20bf 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 36ab6d599ffc 63d07f8db31c 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 36ab6d599ffc 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 96830f3c215f 7596922f4d68 36ab6d599ffc 36ab6d599ffc 7596922f4d68 7596922f4d68 63d07f8db31c 36ab6d599ffc 36ab6d599ffc 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 36ab6d599ffc 36ab6d599ffc 36ab6d599ffc 7596922f4d68 7596922f4d68 5c07d3e9454b 7596922f4d68 7596922f4d68 5f311ca7bd4e 5f311ca7bd4e 36ab6d599ffc 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 36ab6d599ffc 7e7d85c7e7bb 7e7d85c7e7bb 7e7d85c7e7bb 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 464d85b36a64 464d85b36a64 464d85b36a64 464d85b36a64 464d85b36a64 5948aacd93f4 464d85b36a64 7596922f4d68 7596922f4d68 36ab6d599ffc 36ab6d599ffc 36ab6d599ffc 7596922f4d68 36ab6d599ffc bd2fd5338d8d bd2fd5338d8d bd2fd5338d8d bd2fd5338d8d edb3336aa7fc bd2fd5338d8d bd2fd5338d8d 7596922f4d68 7596922f4d68 6cf7a62da1cb 6cf7a62da1cb 6cf7a62da1cb 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 63d07f8db31c 63d07f8db31c 63d07f8db31c 7596922f4d68 36ab6d599ffc 5f311ca7bd4e 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 7596922f4d68 36ab6d599ffc 7596922f4d68 cb4b0fac3871 5c07d3e9454b 36ab6d599ffc 7596922f4d68 7596922f4d68 7596922f4d68 7596922f4d68 36ab6d599ffc 36ab6d599ffc | import os
import uuid
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from django.utils.timezone import now
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
import reversion
from markitup.fields import MarkupField
from model_utils.managers import InheritanceManager
from symposion.conference.models import Section
from symposion.speakers.models import Speaker
class ProposalSection(models.Model):
"""
configuration of proposal submissions for a specific Section.
a section is available for proposals iff:
* it is after start (if there is one) and
* it is before end (if there is one) and
* closed is NULL or False
"""
section = models.OneToOneField(Section)
start = models.DateTimeField(null=True, blank=True)
end = models.DateTimeField(null=True, blank=True)
closed = models.NullBooleanField()
published = models.NullBooleanField()
@classmethod
def available(cls):
return cls._default_manager.filter(
Q(start__lt=now()) | Q(start=None),
Q(end__gt=now()) | Q(end=None),
Q(closed=False) | Q(closed=None),
)
def is_available(self):
if self.closed:
return False
if self.start and self.start > now():
return False
if self.end and self.end < now():
return False
return True
def __unicode__(self):
return self.section.name
class ProposalKind(models.Model):
"""
e.g. talk vs panel vs tutorial vs poster
Note that if you have different deadlines, reviewers, etc. you'll want
to distinguish the section as well as the kind.
"""
section = models.ForeignKey(Section, related_name="proposal_kinds")
name = models.CharField(_("Name"), max_length=100)
slug = models.SlugField()
def __unicode__(self):
return self.name
class ProposalBase(models.Model):
objects = InheritanceManager()
kind = models.ForeignKey(ProposalKind)
title = models.CharField(max_length=100)
description = models.TextField(
_("Brief Description"),
max_length=400, # @@@ need to enforce 400 in UI
help_text=_("If your proposal is accepted this will be made public and printed in the "
"program. Should be one paragraph, maximum 400 characters.")
)
abstract = MarkupField(
_("Detailed Abstract"),
help_text=_("Detailed outline. Will be made public if your proposal is accepted. Edit "
"using <a href='http://daringfireball.net/projects/markdown/basics' "
"target='_blank'>Markdown</a>.")
)
additional_notes = MarkupField(
blank=True,
help_text=_("Anything else you'd like the program committee to know when making their "
"selection: your past experience, etc. This is not made public. Edit using "
"<a href='http://daringfireball.net/projects/markdown/basics' "
"target='_blank'>Markdown</a>.")
)
submitted = models.DateTimeField(
default=now,
editable=False,
)
speaker = models.ForeignKey(Speaker, related_name="proposals")
additional_speakers = models.ManyToManyField(Speaker, through="AdditionalSpeaker",
blank=True)
cancelled = models.BooleanField(default=False)
def can_edit(self):
return True
@property
def section(self):
return self.kind.section
@property
def speaker_email(self):
return self.speaker.email
@property
def number(self):
return str(self.pk).zfill(3)
@property
def status(self):
try:
return self.result.status
except ObjectDoesNotExist:
return _('Undecided')
def speakers(self):
yield self.speaker
speakers = self.additional_speakers.exclude(
additionalspeaker__status=AdditionalSpeaker.SPEAKING_STATUS_DECLINED)
for speaker in speakers:
yield speaker
def notification_email_context(self):
return {
"title": self.title,
"speaker": self.speaker.name,
"speakers": ', '.join([x.name for x in self.speakers()]),
"kind": self.kind.name,
}
reversion.register(ProposalBase)
class AdditionalSpeaker(models.Model):
SPEAKING_STATUS_PENDING = 1
SPEAKING_STATUS_ACCEPTED = 2
SPEAKING_STATUS_DECLINED = 3
SPEAKING_STATUS = [
(SPEAKING_STATUS_PENDING, _("Pending")),
(SPEAKING_STATUS_ACCEPTED, _("Accepted")),
(SPEAKING_STATUS_DECLINED, _("Declined")),
]
speaker = models.ForeignKey(Speaker)
proposalbase = models.ForeignKey(ProposalBase)
status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING)
class Meta:
unique_together = ("speaker", "proposalbase")
def uuid_filename(instance, filename):
ext = filename.split(".")[-1]
filename = "%s.%s" % (uuid.uuid4(), ext)
return os.path.join("document", filename)
class SupportingDocument(models.Model):
proposal = models.ForeignKey(ProposalBase, related_name="supporting_documents")
uploaded_by = models.ForeignKey(User)
created_at = models.DateTimeField(default=now)
file = models.FileField(upload_to=uuid_filename)
description = models.CharField(max_length=140)
def download_url(self):
return reverse("proposal_document_download",
args=[self.pk, os.path.basename(self.file.name).lower()])
|