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
|
from django.db import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from postgresqleu.confreg.models import Conference, ConferenceRegistration
from postgresqleu.confreg.models import RegistrationType
from postgresqleu.util.diffablemodel import DiffableModel
class Wikipage(models.Model, DiffableModel):
conference = models.ForeignKey(Conference, null=False, blank=False, on_delete=models.CASCADE)
url = models.CharField(max_length=100, null=False, blank=False, validators=[
RegexValidator(regex='^[a-zA-Z0-9_-]+$',
message='Invalid character in urlname. Only alphanumerical, underscore and dash are allowed.'), ])
title = models.CharField(max_length=100, null=False, blank=False)
author = models.ForeignKey(ConferenceRegistration, null=False, blank=False, on_delete=models.CASCADE)
publishedat = models.DateTimeField(null=False, blank=False, auto_now=True)
contents = models.TextField(null=False, blank=False)
# Can the public (=anybody registered) view/edit this?
publicview = models.BooleanField(null=False, blank=False, default=False,
verbose_name="Public view",
help_text="Can all confirmed attendees see this page?")
publicedit = models.BooleanField(null=False, blank=False, default=False,
verbose_name="Public edit",
help_text="Can all confirmed attendees edit this page?")
# Do we allow anybody to view the history (we always track history,
# this is only about it being viewable to non-admins)
history = models.BooleanField(null=False, blank=False, default=True, help_text="Can users view the history?")
# Several rounds of permissions. Can be done smarter? Maybe...
viewer_regtype = models.ManyToManyField(RegistrationType, blank=True, related_name='viewer_regtypes', verbose_name="Viewer registration types")
editor_regtype = models.ManyToManyField(RegistrationType, blank=True, related_name='editor_regtypes', verbose_name="Editor registration types")
viewer_attendee = models.ManyToManyField(ConferenceRegistration, blank=True, related_name='viewer_attendees', verbose_name="Viewer attendees")
editor_attendee = models.ManyToManyField(ConferenceRegistration, blank=True, related_name='editor_attendees', verbose_name="Editor attendees")
_unsafe_attributes = ('viewer_regtype', 'editor_regtype', 'viewer_attendee', 'editor_attendee')
class Meta:
unique_together = [
('conference', 'url', )
]
ordering = ('title', )
def __str__(self):
return "{0} ({1})".format(self.url, self.title)
map_manytomany_for_diff = {
'viewer_regtype': 'viewer_regtypes',
'editor_regtype': 'editor_regtypes',
'viewer_attendee': 'viewer_attendees',
'editor_attendee': 'editor_attendees',
}
@property
def viewer_regtypes(self):
return ", ".join([r.regtype for r in self.viewer_regtype.all()])
@property
def editor_regtypes(self):
return ", ".join([r.regtype for r in self.editor_regtype.all()])
@property
def viewer_attendees(self):
return ", ".join([r.fullname for r in self.viewer_attendee.all()])
@property
def editor_attendees(self):
return ", ".join([r.fullname for r in self.editor_attendee.all()])
# When a page is edited, the old version is copied over to the history. A page that has
# never been edited has no history entry. Permission changes are not tracked.
class WikipageHistory(models.Model):
page = models.ForeignKey(Wikipage, null=False, blank=False, db_index=True, on_delete=models.CASCADE)
author = models.ForeignKey(ConferenceRegistration, null=False, blank=False, on_delete=models.CASCADE)
publishedat = models.DateTimeField(null=False, blank=False)
contents = models.TextField(null=False, blank=False)
_safe_attributes = ('id', 'author', 'page', 'publishedat', 'contents')
class Meta:
ordering = ('-publishedat',)
unique_together = (
('page', 'publishedat',)
)
# Subscribers to changes of wikipages
class WikipageSubscriber(models.Model):
page = models.ForeignKey(Wikipage, null=False, blank=False, db_index=True, on_delete=models.CASCADE)
subscriber = models.ForeignKey(ConferenceRegistration, null=False, blank=False, on_delete=models.CASCADE)
def validate_options(value):
pieces = [v.strip() for v in value.split(',')]
if len(pieces) < 2:
raise ValidationError("At least two options must be given")
for v in pieces:
if len(v) < 1:
raise ValidationError("Empty options are not allowed")
if len(v) > 100:
raise ValidationError("Options must be less than 100 characters each")
def validate_optionvalues(value):
if value == '':
return
pieces = [v.strip() for v in value.split(',')]
for v in pieces:
if not v.isdigit():
raise ValidationError("All option values must be numbers!")
if int(v) < 0:
raise ValidationError("All option values must be positive numbers!")
# Signups - attendees can sign up for events
class Signup(models.Model):
conference = models.ForeignKey(Conference, null=False, blank=False, on_delete=models.CASCADE)
author = models.ForeignKey(ConferenceRegistration, null=False, blank=False, on_delete=models.CASCADE)
title = models.CharField(max_length=100, null=False, blank=False)
intro = models.TextField(null=False, blank=False)
deadline = models.DateTimeField(null=True, blank=True)
maxsignups = models.IntegerField(null=False, blank=False, default=-1)
options = models.CharField(max_length=1000, null=False, blank=True, help_text="Comma separated list of options to choose.", validators=[validate_options, ])
optionvalues = models.CharField(max_length=1000, null=False, blank=True, help_text="Optional comma separated list of how much each choice counts towards the max value", validators=[validate_optionvalues, ])
notify_changes = models.BooleanField(null=False, blank=False, default=False, help_text="Send email notifications when attendees sign up or change their signup information")
public = models.BooleanField(null=False, blank=False, default=False, help_text="All attendees can sign up")
visible = models.BooleanField(null=False, blank=False, default=False, help_text="Show who have signed up to all invited attendees")
regtypes = models.ManyToManyField(RegistrationType, blank=True, verbose_name="Available to registration types", related_name="user_regtypes")
attendees = models.ManyToManyField(ConferenceRegistration, blank=True, verbose_name="Available to attendees", related_name="user_attendees")
class Meta:
ordering = ('deadline', 'title', )
def __str__(self):
return self.title
def clean(self):
if self.options:
if self.optionvalues:
if len(self.options.split(',')) != len(self.optionvalues.split(',')):
raise ValidationError({"optionvalues": "Options and optionvalues must have the same number of entries!"})
else:
# No options, so there must be no optionvalues
if self.optionvalues:
raise ValidationError({"optionvalues": "Cannot specify optionvalues if options are not specified!"})
class AttendeeSignup(models.Model):
signup = models.ForeignKey(Signup, null=False, blank=False, on_delete=models.CASCADE)
attendee = models.ForeignKey(ConferenceRegistration, null=False, blank=False, on_delete=models.CASCADE)
choice = models.CharField(max_length=100, null=False, blank=True)
saved = models.DateTimeField(null=False, blank=False, auto_now=True)
_safe_attributes = ('choice', 'saved', 'attendee', )
class Meta:
unique_together = (
('signup', 'attendee',),
)
|