Merge lp:~cjohnston/summit/registration-form into lp:summit
- registration-form
- Merge into trunk
Proposed by
Chris Johnston
Status: | Merged |
---|---|
Approved by: | Chris Johnston |
Approved revision: | 522 |
Merged at revision: | 523 |
Proposed branch: | lp:~cjohnston/summit/registration-form |
Merge into: | lp:summit |
Diff against target: |
595 lines (+503/-1) 10 files modified
EXTERNALS (+7/-0) summit/common/widgets.py (+122/-0) summit/media/css/style.css (+17/-0) summit/media/js/events-ui.js (+11/-0) summit/schedule/forms.py (+31/-0) summit/schedule/templates/schedule/form.html (+41/-0) summit/schedule/tests/__init__.py (+1/-0) summit/schedule/tests/registration.py (+222/-0) summit/schedule/views.py (+46/-1) summit/urls.py (+5/-0) |
To merge this branch: | bzr merge lp:~cjohnston/summit/registration-form |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Adnane Belmadiaf | Approve | ||
Review via email: mp+156978@code.launchpad.net |
This proposal supersedes a proposal from 2013-04-03.
Commit message
Adds a registration form to register as attending a sprint.
Description of the change
This adds a registration form as well as a generic form.html template, which I hope to be able to reuse for more (all) forms instead of having to have a custom template for each form. Note: This does not include a link to the registration page. summit.html will need some re-work for that, so I will be doing that in a separate branch.
To post a comment you must log in.
Revision history for this message
Adnane Belmadiaf (daker) wrote : | # |
- 519. By Chris Johnston
-
Use async loading
- 520. By Chris Johnston
-
Fixes issue with select widget
- 521. By Chris Johnston
-
Update from trunk
- 522. By Chris Johnston
-
Removes css/js
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'EXTERNALS' |
2 | --- EXTERNALS 2012-04-22 20:20:10 +0000 |
3 | +++ EXTERNALS 2013-04-08 21:02:19 +0000 |
4 | @@ -19,3 +19,10 @@ |
5 | |
6 | - Twitter JS |
7 | http://twitter.com/javascripts/blogger.js |
8 | + |
9 | +- Date Picker |
10 | +provided by the JQuery UI project. See http://jqueryui.com/ |
11 | + |
12 | +- DateTimeWidget inspired by: |
13 | +http://copiesofcopies.org/webl/2010/04/26/a-better-datetime-widget-for-django/ |
14 | + |
15 | |
16 | === added file 'summit/common/widgets.py' |
17 | --- summit/common/widgets.py 1970-01-01 00:00:00 +0000 |
18 | +++ summit/common/widgets.py 2013-04-08 21:02:19 +0000 |
19 | @@ -0,0 +1,122 @@ |
20 | +# -*- coding: utf-8 -*- |
21 | +from datetime import time |
22 | +from time import strptime, strftime |
23 | + |
24 | +from django import forms |
25 | + |
26 | + |
27 | +class DateWidget(forms.DateInput): |
28 | + """ |
29 | + A more-friendly date widget with a pop-up calendar. |
30 | + """ |
31 | + def __init__(self, attrs=None): |
32 | + self.date_class = 'datepicker' |
33 | + if not attrs: |
34 | + attrs = {} |
35 | + if 'date_class' in attrs: |
36 | + self.date_class = attrs.pop('date_class') |
37 | + if 'class' not in attrs: |
38 | + attrs['class'] = 'date' |
39 | + |
40 | + super(DateWidget, self).__init__(attrs=attrs) |
41 | + |
42 | + def render(self, name, value, attrs=None): |
43 | + return '<span class="%s">%s</span>' % ( |
44 | + self.date_class, |
45 | + super(DateWidget, self).render(name, value, attrs) |
46 | + ) |
47 | + |
48 | + |
49 | +class TimeWidget(forms.MultiWidget): |
50 | + """ |
51 | + A more-friendly time widget. |
52 | + """ |
53 | + def __init__(self, attrs=None): |
54 | + self.time_class = 'timepicker' |
55 | + if not attrs: |
56 | + attrs = {} |
57 | + if 'time_class' in attrs: |
58 | + self.time_class = attrs.pop('time_class') |
59 | + if 'class' not in attrs: |
60 | + attrs['class'] = 'time' |
61 | + |
62 | + widgets = ( |
63 | + forms.Select( |
64 | + attrs=attrs, |
65 | + choices=[(i + 1, "%02d" % (i + 1)) for i in range(0, 12)], |
66 | + ), |
67 | + forms.Select( |
68 | + attrs=attrs, |
69 | + choices=[(i, "%02d" % i) for i in range(00, 60, 15)], |
70 | + ), |
71 | + forms.Select( |
72 | + attrs=attrs, |
73 | + choices=[('AM', 'AM'), ('PM', 'PM')], |
74 | + ) |
75 | + ) |
76 | + |
77 | + super(TimeWidget, self).__init__(widgets, attrs) |
78 | + |
79 | + def decompress(self, value): |
80 | + if isinstance(value, str): |
81 | + value = strptime(value, '%I:%M %p') |
82 | + hour = int(value.tm_hour) |
83 | + minute = int(value.tm_min) |
84 | + if hour < 12: |
85 | + meridian = 'AM' |
86 | + else: |
87 | + meridian = 'PM' |
88 | + hour -= 12 |
89 | + return (hour, minute, meridian) |
90 | + |
91 | + elif isinstance(value, time): |
92 | + hour = int(value.strftime("%I")) |
93 | + minute = int(value.strftime("%M")) |
94 | + meridian = value.strftime("%p") |
95 | + return (hour, minute, meridian) |
96 | + return (None, None, None) |
97 | + |
98 | + def value_from_datadict(self, data, files, name): |
99 | + value = super(TimeWidget, self).value_from_datadict(data, files, name) |
100 | + t = strptime( |
101 | + "%02d:%02d %s" % ( |
102 | + int(value[0]), |
103 | + int(value[1]), |
104 | + value[2] |
105 | + ), |
106 | + "%I:%M %p", |
107 | + ) |
108 | + return strftime("%H:%M:%S", t) |
109 | + |
110 | + def format_output(self, rendered_widgets): |
111 | + return '<span class="%s">%s%s%s</span>' % ( |
112 | + self.time_class, |
113 | + rendered_widgets[0], rendered_widgets[1], rendered_widgets[2] |
114 | + ) |
115 | + |
116 | + |
117 | +class DateTimeWidget(forms.SplitDateTimeWidget): |
118 | + """ |
119 | + A more-friendly date/time widget. |
120 | + |
121 | + Inspired by: |
122 | + |
123 | + http://copiesofcopies.org/webl/2010/04/26/a-better-datetime-widget-for-django/ |
124 | + """ |
125 | + def __init__(self, attrs=None, date_format=None, time_format=None): |
126 | + super(DateTimeWidget, self).__init__(attrs, date_format, time_format) |
127 | + self.widgets = ( |
128 | + DateWidget(attrs=attrs), |
129 | + TimeWidget(attrs=attrs), |
130 | + ) |
131 | + |
132 | + def decompress(self, value): |
133 | + if value: |
134 | + d = strftime("%Y-%m-%d", value.timetuple()) |
135 | + t = strftime("%I:%M %p", value.timetuple()) |
136 | + return (d, t) |
137 | + else: |
138 | + return (None, None) |
139 | + |
140 | + def format_output(self, rendered_widgets): |
141 | + return '%s%s' % (rendered_widgets[0], rendered_widgets[1]) |
142 | |
143 | === modified file 'summit/media/css/style.css' |
144 | --- summit/media/css/style.css 2012-01-22 18:36:40 +0000 |
145 | +++ summit/media/css/style.css 2013-04-08 21:02:19 +0000 |
146 | @@ -66,3 +66,20 @@ |
147 | .summit-columns ul li h3 a:hover { text-decoration: underline; } |
148 | .summit-columns ul li img { padding: 10px 0 5px; } |
149 | .summit-columns p { margin-bottom: 5px; } |
150 | + |
151 | +#id_start_utc_0, #id_start_utc_1, |
152 | +#id_end_utc_0, #id_end_utc_1, |
153 | +#id_start_utc_1_0, #id_start_utc_1_1, #id_start_utc_1_2, |
154 | +#id_end_utc_1_0, #id_end_utc_1_1, #id_end_utc_1_2 { |
155 | + width: 100px; |
156 | + display: inline; |
157 | +} |
158 | + |
159 | +#id_start_utc_1_0, #id_start_utc_1_1, #id_start_utc_1_2, |
160 | +#id_end_utc_1_0, #id_end_utc_1_1, #id_end_utc_1_2 { |
161 | + width: 60px; |
162 | +} |
163 | + |
164 | +#id_name, #id_announce, #id_registration { |
165 | + width: 350px; |
166 | +} |
167 | |
168 | === added file 'summit/media/js/events-ui.js' |
169 | --- summit/media/js/events-ui.js 1970-01-01 00:00:00 +0000 |
170 | +++ summit/media/js/events-ui.js 2013-04-08 21:02:19 +0000 |
171 | @@ -0,0 +1,11 @@ |
172 | +$(document).ready(function(){ |
173 | + |
174 | + $.datepicker.setDefaults({ |
175 | + showOn: 'focus', |
176 | + dateFormat: 'yy-mm-dd', |
177 | + }); |
178 | + |
179 | + $("#id_start_utc_0").datepicker(); |
180 | + $("#id_end_utc_0").datepicker(); |
181 | + |
182 | +}); |
183 | |
184 | === modified file 'summit/schedule/forms.py' |
185 | --- summit/schedule/forms.py 2013-03-09 05:14:19 +0000 |
186 | +++ summit/schedule/forms.py 2013-04-08 21:02:19 +0000 |
187 | @@ -14,6 +14,7 @@ |
188 | # You should have received a copy of the GNU Affero General Public License |
189 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
190 | |
191 | +from django.conf import settings |
192 | from django import forms |
193 | |
194 | from summit.schedule.models.meetingmodel import Meeting |
195 | @@ -21,6 +22,7 @@ |
196 | from summit.schedule.models.participantmodel import Participant |
197 | |
198 | from common.forms import RenderableMixin |
199 | +from common.widgets import DateTimeWidget |
200 | |
201 | |
202 | class MultipleAttendeeField(forms.ModelMultipleChoiceField): |
203 | @@ -226,3 +228,32 @@ |
204 | fields = ('hangout_url', 'broadcast_url') |
205 | |
206 | broadcast_url = YouTubeEmbedURL(label='Broadcast URL') |
207 | + |
208 | + |
209 | +class Registration(forms.ModelForm, RenderableMixin): |
210 | + class Meta: |
211 | + model = Attendee |
212 | + fields = ( |
213 | + 'start_utc', |
214 | + 'end_utc', |
215 | + 'crew', |
216 | + ) |
217 | + |
218 | + def __init__(self, *args, **kargs): |
219 | + super(Registration, self).__init__(*args, **kargs) |
220 | + self.fields['start_utc'].widget = DateTimeWidget() |
221 | + self.fields['end_utc'].widget = DateTimeWidget() |
222 | + |
223 | + def clean(self): |
224 | + begin = self.cleaned_data.get('start_utc') |
225 | + end = self.cleaned_data.get('end_utc') |
226 | + if begin and end and begin > end: |
227 | + raise forms.ValidationError( |
228 | + "Availability can not end before it starts." |
229 | + ) |
230 | + return self.cleaned_data |
231 | + |
232 | + def save(self, commit=True): |
233 | + instance = super(Registration, self).save(commit) |
234 | + instance.from_launchpad = False |
235 | + instance.save() |
236 | |
237 | === added file 'summit/schedule/templates/schedule/form.html' |
238 | --- summit/schedule/templates/schedule/form.html 1970-01-01 00:00:00 +0000 |
239 | +++ summit/schedule/templates/schedule/form.html 2013-04-08 21:02:19 +0000 |
240 | @@ -0,0 +1,41 @@ |
241 | +{% extends "base.html" %} |
242 | + |
243 | +{% block page_name %}{{ form_title }} - {{ summit.title }}{%endblock %} |
244 | +{% block sub_nav %}{% endblock %} |
245 | + |
246 | +{% block closure %} |
247 | +<script type="text/javascript"><!-- |
248 | +$(document).ready(function(){ |
249 | + $('span[rel*=help]').colorTip({color:'orange'}); |
250 | +}); |
251 | +--></script> |
252 | +<style> |
253 | +form ul { |
254 | + height: 12em; |
255 | + overflow-y: scroll; |
256 | + overflow-x: hidden; |
257 | +} |
258 | +</style> |
259 | +{% endblock %} |
260 | + |
261 | + |
262 | +{% block content %} |
263 | +<div class="row"> |
264 | + <article id="form" class="span-8"> |
265 | + {% if form.errors %} |
266 | + <p style="color: red;"> |
267 | + Please correct the error{{ form.errors|pluralize }} below. |
268 | + </p> |
269 | + {% endif %} |
270 | + |
271 | + <form action="{{ request.path_info }}" method="POST">{% csrf_token %} |
272 | + <fieldset> |
273 | + <h3>{{ form_title }}</h3> |
274 | + {{ form.as_template }} |
275 | + {% if is_popup %}<input type="hidden" name="_popup" value="1">{% endif %} |
276 | + <input type="submit" name="submit" value="Create" class="submit-button" /> |
277 | + </fieldset> |
278 | + </form> |
279 | + </article> |
280 | +</div> |
281 | +{% endblock %} |
282 | |
283 | === modified file 'summit/schedule/tests/__init__.py' |
284 | --- summit/schedule/tests/__init__.py 2013-03-14 20:52:12 +0000 |
285 | +++ summit/schedule/tests/__init__.py 2013-04-08 21:02:19 +0000 |
286 | @@ -31,3 +31,4 @@ |
287 | from schedule import * |
288 | from summit_model import * |
289 | from propose_meeting import * |
290 | +from registration import RegistrationTestCase |
291 | |
292 | === added file 'summit/schedule/tests/registration.py' |
293 | --- summit/schedule/tests/registration.py 1970-01-01 00:00:00 +0000 |
294 | +++ summit/schedule/tests/registration.py 2013-04-08 21:02:19 +0000 |
295 | @@ -0,0 +1,222 @@ |
296 | +# The Summit Scheduler web application |
297 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
298 | +# |
299 | +# This program is free software: you can redistribute it and/or modify |
300 | +# it under the terms of the GNU Affero General Public License as |
301 | +# published by the Free Software Foundation, either version 3 of the |
302 | +# License, or (at your option) any later version. |
303 | +# |
304 | +# This program is distributed in the hope that it will be useful, |
305 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
306 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
307 | +# GNU Affero General Public License for more details. |
308 | +# |
309 | +# You should have received a copy of the GNU Affero General Public License |
310 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
311 | + |
312 | +import datetime |
313 | + |
314 | +from django import test as djangotest |
315 | +from django.core.urlresolvers import reverse |
316 | + |
317 | +from django.contrib.auth.models import User |
318 | +from django.test.client import Client |
319 | + |
320 | +from model_mommy import mommy as factory |
321 | + |
322 | +from summit.schedule.models import ( |
323 | + Summit, |
324 | + Attendee, |
325 | +) |
326 | + |
327 | + |
328 | +class RegistrationTestCase(djangotest.TestCase): |
329 | + """ |
330 | + Tests for registering to attend a Summit |
331 | + """ |
332 | + c = Client() |
333 | + |
334 | + def setUp(self): |
335 | + self.now = datetime.datetime.utcnow() |
336 | + self.one_hour = datetime.timedelta(0, 3600) |
337 | + self.one_day = datetime.timedelta(days=1) |
338 | + self.week = datetime.timedelta(days=5) |
339 | + self.end_summit = self.now + self.week |
340 | + self.summit = factory.make_one( |
341 | + Summit, |
342 | + name='test-summit', |
343 | + title='Test Summit', |
344 | + virtual_summit=True, |
345 | + date_start=self.now, |
346 | + date_end=self.now + self.week, |
347 | + timezone='UTC', |
348 | + ) |
349 | + |
350 | + self.user1 = factory.make_one( |
351 | + User, |
352 | + username='testuser', |
353 | + first_name='Test', |
354 | + last_name='User', |
355 | + is_active=True, |
356 | + is_superuser=False, |
357 | + ) |
358 | + self.user1.set_password('password') |
359 | + self.user1.save() |
360 | + |
361 | + def create_attendee(self): |
362 | + self.attendee1 = factory.make_one( |
363 | + Attendee, |
364 | + summit=self.summit, |
365 | + user=self.user1, |
366 | + start_utc=self.now, |
367 | + end_utc=self.now+self.week |
368 | + ) |
369 | + |
370 | + def tearDown(self): |
371 | + self.client.logout() |
372 | + |
373 | + def login(self): |
374 | + logged_in = self.c.login( |
375 | + username='testuser', |
376 | + password='password') |
377 | + self.assertTrue(logged_in) |
378 | + |
379 | + def get_attendee(self): |
380 | + attendee = Attendee.objects.get(user=self.user1) |
381 | + return attendee |
382 | + |
383 | + def with_summit_registration_times(self): |
384 | + """ |
385 | + Using the start and end of the summit as the registration times |
386 | + """ |
387 | + self.start_date = self.now.strftime("%Y-%m-%d") |
388 | + self.start_hour = self.now.strftime("%I") |
389 | + self.start_minute = self.now.strftime("%M") |
390 | + self.start_period = self.now.strftime("%p") |
391 | + self.end_hour = self.end_summit.strftime("%I") |
392 | + self.end_minute = self.end_summit.strftime("%M") |
393 | + self.end_period = self.end_summit.strftime("%p") |
394 | + self.end_date = self.end_summit.strftime("%Y-%m-%d") |
395 | + self.edit_registration_form() |
396 | + attendee = self.get_attendee() |
397 | + self.assertEqual( |
398 | + attendee.start_utc.replace(second=0), |
399 | + self.now.replace(second=0, microsecond=0), |
400 | + ) |
401 | + self.assertEqual( |
402 | + attendee.end_utc.replace(second=0, microsecond=0), |
403 | + self.end_summit.replace(second=0, microsecond=0), |
404 | + ) |
405 | + |
406 | + def with_custom_registration_times(self): |
407 | + """ |
408 | + Using custom start and end registration times |
409 | + """ |
410 | + start = self.now + self.one_day |
411 | + self.start_date = start.strftime("%Y-%m-%d") |
412 | + self.start_hour = self.now.strftime("%I") |
413 | + self.start_minute = self.now.strftime("%M") |
414 | + self.start_period = self.now.strftime("%p") |
415 | + self.end_hour = self.end_summit.strftime("%I") |
416 | + self.end_minute = self.end_summit.strftime("%M") |
417 | + self.end_period = self.end_summit.strftime("%p") |
418 | + self.end_date = self.end_summit.strftime("%Y-%m-%d") |
419 | + self.edit_registration_form() |
420 | + attendee = self.get_attendee() |
421 | + self.assertEqual( |
422 | + attendee.start_utc.replace(second=0), |
423 | + start.replace(second=0, microsecond=0), |
424 | + ) |
425 | + self.assertEqual( |
426 | + attendee.end_utc.replace(second=0, microsecond=0), |
427 | + self.end_summit.replace(second=0, microsecond=0), |
428 | + ) |
429 | + |
430 | + def edit_registration_form(self): |
431 | + """ |
432 | + Tests that a user can register for a Summit |
433 | + """ |
434 | + # Define data to fill our the form |
435 | + |
436 | + # Post the form |
437 | + post = self.c.post( |
438 | + reverse( |
439 | + 'registration', |
440 | + args=(self.summit.name,) |
441 | + ), |
442 | + data={ |
443 | + 'end_utc_0': self.end_date, |
444 | + 'end_utc_1_0': self.end_hour, |
445 | + 'end_utc_1_1': self.end_minute, |
446 | + 'end_utc_1_2': self.end_period, |
447 | + 'start_utc_1_0': self.start_hour, |
448 | + 'start_utc_1_1': self.start_minute, |
449 | + 'start_utc_1_2': self.start_period, |
450 | + 'start_utc_0': self.start_date, |
451 | + } |
452 | + ) |
453 | + |
454 | + # A successful post should redirect to the summit page |
455 | + response = reverse( |
456 | + 'summit.schedule.views.summit', |
457 | + args=(self.summit.name,) |
458 | + ) |
459 | + self.assertEqual(post.status_code, 302) |
460 | + self.assertRedirects(post, response) |
461 | + attendee = self.get_attendee() |
462 | + self.assertEqual(attendee.user, self.user1) |
463 | + self.assertEqual(attendee.from_launchpad, False) |
464 | + |
465 | + def test_non_attendee_registers(self): |
466 | + self.login() |
467 | + self.assertRaises(Attendee.DoesNotExist, lambda: self.get_attendee()) |
468 | + rev_args = [self.summit.name, ] |
469 | + response = self.c.get(reverse('registration', args=rev_args)) |
470 | + self.assertEqual(response.status_code, 200) |
471 | + self.assertTemplateUsed(response, 'schedule/form.html') |
472 | + self.assertIn('Register for ' + self.summit.title, response.content) |
473 | + self.with_summit_registration_times() |
474 | + |
475 | + def test_attendee_updates_registration(self): |
476 | + self.create_attendee() |
477 | + self.login() |
478 | + self.assertEquals( |
479 | + self.user1.username, |
480 | + self.get_attendee().user.username, |
481 | + ) |
482 | + rev_args = [self.summit.name, ] |
483 | + response = self.c.get(reverse('registration', args=rev_args)) |
484 | + self.assertEqual(response.status_code, 200) |
485 | + self.assertTemplateUsed(response, 'schedule/form.html') |
486 | + self.assertIn( |
487 | + 'Update registration for ' + self.summit.title, |
488 | + response.content |
489 | + ) |
490 | + self.with_custom_registration_times() |
491 | + |
492 | + def test_update_registration_from_launchpad_true(self): |
493 | + """ |
494 | + update resgistration with from_launchpad=True |
495 | + to save from_launchpad=False |
496 | + """ |
497 | + self.create_attendee() |
498 | + self.attendee1.from_launchpad = True |
499 | + self.attendee1.save() |
500 | + self.login() |
501 | + self.assertEquals( |
502 | + self.user1.username, |
503 | + self.get_attendee().user.username, |
504 | + ) |
505 | + self.assertEquals( |
506 | + True, |
507 | + self.get_attendee().from_launchpad, |
508 | + ) |
509 | + rev_args = [self.summit.name, ] |
510 | + response = self.c.get(reverse('registration', args=rev_args)) |
511 | + self.assertEqual(response.status_code, 200) |
512 | + self.assertTemplateUsed(response, 'schedule/form.html') |
513 | + self.assertIn( |
514 | + 'Update registration for ' + self.summit.title, |
515 | + response.content |
516 | + ) |
517 | + self.with_custom_registration_times() |
518 | |
519 | === modified file 'summit/schedule/views.py' |
520 | --- summit/schedule/views.py 2013-03-15 01:06:10 +0000 |
521 | +++ summit/schedule/views.py 2013-04-08 21:02:19 +0000 |
522 | @@ -52,7 +52,8 @@ |
523 | MeetingReview, |
524 | AttendMeeting, |
525 | OrganizerChangeAttend, |
526 | - EditMeetingHangout |
527 | + EditMeetingHangout, |
528 | + Registration, |
529 | ) |
530 | |
531 | __all__ = ( |
532 | @@ -1173,3 +1174,47 @@ |
533 | context, |
534 | RequestContext(request) |
535 | ) |
536 | + |
537 | + |
538 | +@login_required |
539 | +@summit_required |
540 | +def registration_form(request, summit, attendee): |
541 | + registration_args = dict() |
542 | + |
543 | + if attendee is None: |
544 | + attendee = Attendee( |
545 | + user=request.user, |
546 | + summit=summit, |
547 | + from_launchpad=False, |
548 | + start_utc=summit.start or summit.date_start, |
549 | + end_utc=summit.end or summit.date_end, |
550 | + ) |
551 | + registration_args['instance'] = attendee |
552 | + form_title="Register for %s" % summit.title |
553 | + else: |
554 | + registration_args['instance'] = attendee |
555 | + form_title="Update registration for %s" % summit.title |
556 | + |
557 | + if request.method == 'POST': |
558 | + form = Registration(data=request.POST, **registration_args) |
559 | + if form.is_valid(): |
560 | + form.save() |
561 | + return HttpResponseRedirect( |
562 | + reverse( |
563 | + 'summit.schedule.views.summit', |
564 | + args=(summit.name,) |
565 | + ) |
566 | + ) |
567 | + else: |
568 | + form = Registration(**registration_args) |
569 | + |
570 | + context = { |
571 | + 'summit': summit, |
572 | + 'form': form, |
573 | + 'form_title': form_title, |
574 | + } |
575 | + return render_to_response( |
576 | + 'schedule/form.html', |
577 | + context, |
578 | + RequestContext(request) |
579 | + ) |
580 | |
581 | === modified file 'summit/urls.py' |
582 | --- summit/urls.py 2013-02-26 19:31:21 +0000 |
583 | +++ summit/urls.py 2013-04-08 21:02:19 +0000 |
584 | @@ -68,6 +68,11 @@ |
585 | (r'^(?P<summit_name>[\w-]+)/$', 'summit'), |
586 | (r'^(?P<summit_name>[\w-]+)/mobile/$', 'mobile'), |
587 | (r'^(?P<summit_name>[\w-]+)/search/$', 'search'), |
588 | + url( |
589 | + r'^(?P<summit_name>[\w-]+)/registration/$', |
590 | + 'registration_form', |
591 | + name='registration', |
592 | + ), |
593 | (r'^(?P<summit_name>[\w-]+)/propose_meeting/$', 'propose_meeting'), |
594 | (r'^(?P<summit_name>[\w-]+)/edit_meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', |
595 | 'edit_meeting'), |
The timewidget doesn't select the correct value( see bug 1164296 ), for the forms.Select there should an initial value if the user have already set his availability.