django 2.0

This commit is contained in:
Élie Bouttier 2017-12-10 13:32:19 +01:00
parent c5af037435
commit 6cbbb6bd1f
19 changed files with 181 additions and 189 deletions

View File

@ -1,12 +1,12 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.urlresolvers import reverse from django.urls import reverse
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
class Profile(models.Model): class Profile(models.Model):
user = models.OneToOneField(User) user = models.OneToOneField(User, on_delete=models.CASCADE)
phone_number = models.CharField(max_length=16, blank=True, default='', verbose_name=_('Phone number')) phone_number = models.CharField(max_length=16, blank=True, default='', verbose_name=_('Phone number'))
sms_prefered = models.BooleanField(default=False, verbose_name=_('SMS prefered')) sms_prefered = models.BooleanField(default=False, verbose_name=_('SMS prefered'))
biography = models.TextField(blank=True, verbose_name=_('Biography')) biography = models.TextField(blank=True, verbose_name=_('Biography'))

View File

@ -1,15 +1,12 @@
from django.conf import settings from django.conf import settings
from django.conf.urls import include, url from django.urls import include, path
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^profile/$', views.profile, name='profile'), path('profile/', views.profile, name='profile'),
url(r'accounts/login/', views.EmailLoginView.as_view(), {'extra_context': {'buttons': [views.RESET_PASSWORD_BUTTON]}}, name='login'), path('accounts/login/', views.EmailLoginView.as_view(), {'extra_context': {'buttons': [views.RESET_PASSWORD_BUTTON]}}, name='login'),
#url(r'^login/$', auth_views.login, {'extra_context': {'buttons': [views.RESET_PASSWORD_BUTTON]}}, name='login'), path('logout/', auth_views.logout, {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout'),
url(r'^logout/$', auth_views.logout, {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout'), path('', include('django.contrib.auth.urls')),
#url(r'^avatar/', include('avatar.urls')),
url(r'', include('django.contrib.auth.urls')),
#url(r'', include('registration.backends.default.urls')),
] ]

8
cfp/converters.py Normal file
View File

@ -0,0 +1,8 @@
class SignedIntConverter:
regex = '[+-]?[0-9]+'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%+d' % value

View File

@ -19,7 +19,7 @@ def speaker_required(view_func):
except ValueError: except ValueError:
raise Http404 raise Http404
speaker = get_object_or_404(Participant, site=request.conference.site, token=speaker_token) speaker = get_object_or_404(Participant, site=request.conference.site, token=speaker_token)
elif request.user.is_authenticated(): elif request.user.is_authenticated:
speaker = get_object_or_404(Participant, site=request.conference.site, email=request.user.email) speaker = get_object_or_404(Participant, site=request.conference.site, email=request.user.email)
else: else:
raise PermissionDenied raise PermissionDenied
@ -37,7 +37,7 @@ def volunteer_required(view_func):
except ValueError: except ValueError:
raise Http404 raise Http404
volunteer = get_object_or_404(Volunteer, site=request.conference.site, token=volunteer_token) volunteer = get_object_or_404(Volunteer, site=request.conference.site, token=volunteer_token)
elif request.user.is_authenticated(): elif request.user.is_authenticated:
volunteer = get_object_or_404(Volunteer, site=request.conference.site, email=request.user.email) volunteer = get_object_or_404(Volunteer, site=request.conference.site, email=request.user.email)
else: else:
raise PermissionDenied raise PermissionDenied
@ -48,7 +48,7 @@ def volunteer_required(view_func):
def staff_required(view_func): def staff_required(view_func):
def _is_staff(request, *args, **kwargs): def _is_staff(request, *args, **kwargs):
if not request.user.is_authenticated(): if not request.user.is_authenticated:
return login_required(view_func)(request, *args, **kwargs) return login_required(view_func)(request, *args, **kwargs)
elif is_staff(request, request.user): elif is_staff(request, request.user):
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)

View File

@ -1,6 +1,6 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse from django.urls import reverse
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
@ -117,7 +117,7 @@ class Participant(PonyConfModel):
notes = models.TextField(default='', blank=True, verbose_name=_("Notes"), notes = models.TextField(default='', blank=True, verbose_name=_("Notes"),
help_text=_('This field is only visible by organizers.')) help_text=_('This field is only visible by organizers.'))
vip = models.BooleanField(default=False, verbose_name=_('Invited speaker')) vip = models.BooleanField(default=False, verbose_name=_('Invited speaker'))
conversation = models.OneToOneField(MessageThread) conversation = models.OneToOneField(MessageThread, on_delete=models.PROTECT)
objects = ParticipantManager() objects = ParticipantManager()
@ -332,14 +332,14 @@ class Talk(PonyConfModel):
slug = AutoSlugField(populate_from='title', unique=True) slug = AutoSlugField(populate_from='title', unique=True)
description = models.TextField(verbose_name=_('Description of your talk'), description = models.TextField(verbose_name=_('Description of your talk'),
help_text=_('This description will be visible on the program.')) help_text=_('This description will be visible on the program.'))
track = models.ForeignKey(Track, blank=True, null=True, verbose_name=_('Track')) track = models.ForeignKey(Track, blank=True, null=True, verbose_name=_('Track'), on_delete=models.SET_NULL)
tags = models.ManyToManyField(Tag, blank=True) tags = models.ManyToManyField(Tag, blank=True)
notes = models.TextField(blank=True, verbose_name=_('Message to organizers'), notes = models.TextField(blank=True, verbose_name=_('Message to organizers'),
help_text=_('If you have any constraint or if you have anything that may ' help_text=_('If you have any constraint or if you have anything that may '
'help you to select your talk, like a video or slides of your' 'help you to select your talk, like a video or slides of your'
' talk, please write it down here. This field will only be ' ' talk, please write it down here. This field will only be '
'visible by organizers.')) 'visible by organizers.'))
category = models.ForeignKey(TalkCategory, verbose_name=_('Talk Category')) category = models.ForeignKey(TalkCategory, verbose_name=_('Talk Category'), on_delete=models.PROTECT)
videotaped = models.BooleanField(_("I'm ok to be recorded on video"), default=True) videotaped = models.BooleanField(_("I'm ok to be recorded on video"), default=True)
video_licence = models.CharField(choices=LICENCES, default='CC-BY-SA', video_licence = models.CharField(choices=LICENCES, default='CC-BY-SA',
max_length=10, verbose_name=_("Video licence")) max_length=10, verbose_name=_("Video licence"))
@ -348,13 +348,13 @@ class Talk(PonyConfModel):
confirmed = models.NullBooleanField(default=None) confirmed = models.NullBooleanField(default=None)
start_date = models.DateTimeField(null=True, blank=True, default=None, verbose_name=_('Beginning date and time')) start_date = models.DateTimeField(null=True, blank=True, default=None, verbose_name=_('Beginning date and time'))
duration = models.PositiveIntegerField(default=0, verbose_name=_('Duration (min)')) duration = models.PositiveIntegerField(default=0, verbose_name=_('Duration (min)'))
room = models.ForeignKey(Room, blank=True, null=True, default=None) room = models.ForeignKey(Room, blank=True, null=True, default=None, on_delete=models.SET_NULL)
plenary = models.BooleanField(default=False) plenary = models.BooleanField(default=False)
materials = models.FileField(null=True, blank=True, upload_to=talks_materials_destination, verbose_name=_('Materials'), materials = models.FileField(null=True, blank=True, upload_to=talks_materials_destination, verbose_name=_('Materials'),
help_text=_('You can use this field to share some materials related to your intervention.')) help_text=_('You can use this field to share some materials related to your intervention.'))
video = models.URLField(max_length=1000, blank=True, default='', verbose_name='Video URL') video = models.URLField(max_length=1000, blank=True, default='', verbose_name='Video URL')
token = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) token = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
conversation = models.OneToOneField(MessageThread) conversation = models.OneToOneField(MessageThread, on_delete=models.PROTECT)
objects = TalkManager() objects = TalkManager()
@ -445,8 +445,8 @@ class Talk(PonyConfModel):
class Vote(PonyConfModel): class Vote(PonyConfModel):
talk = models.ForeignKey(Talk) talk = models.ForeignKey(Talk, on_delete=models.CASCADE)
user = models.ForeignKey(User) user = models.ForeignKey(User, on_delete=models.CASCADE)
vote = models.IntegerField(validators=[MinValueValidator(-2), MaxValueValidator(2)], default=0) vote = models.IntegerField(validators=[MinValueValidator(-2), MaxValueValidator(2)], default=0)
class Meta: class Meta:
@ -491,7 +491,7 @@ class Volunteer(PonyConfModel):
notes = models.TextField(default='', blank=True, verbose_name=_('Notes'), notes = models.TextField(default='', blank=True, verbose_name=_('Notes'),
help_text=_('If you have some constraints, you can indicate them here.')) help_text=_('If you have some constraints, you can indicate them here.'))
activities = models.ManyToManyField(Activity, blank=True, related_name='volunteers', verbose_name=_('Activities')) activities = models.ManyToManyField(Activity, blank=True, related_name='volunteers', verbose_name=_('Activities'))
conversation = models.OneToOneField(MessageThread) conversation = models.OneToOneField(MessageThread, on_delete=models.PROTECT)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('volunteer-details', kwargs={'volunteer_id': self.pk}) return reverse('volunteer-details', kwargs={'volunteer_id': self.pk})

View File

@ -3,7 +3,7 @@ from django.utils.safestring import mark_safe
from django.utils.html import escape from django.utils.html import escape
from django.utils.timezone import localtime, now from django.utils.timezone import localtime, now
from django.core.cache import cache from django.core.cache import cache
from django.core.urlresolvers import reverse from django.urls import reverse
from django.template.loader import get_template from django.template.loader import get_template
from django.conf import settings from django.conf import settings
@ -298,9 +298,9 @@ class Program:
if not result: if not result:
result = getattr(self, '_as_%s' % output)(**kwargs) result = getattr(self, '_as_%s' % output)(**kwargs)
cache.set(cache_entry, result, 3 * 60 * 60) # 3H cache.set(cache_entry, result, 3 * 60 * 60) # 3H
return mark_safe(result) return result
else: else:
return mark_safe(getattr(self, '_as_%s' % output)(**kwargs)) return getattr(self, '_as_%s' % output)(**kwargs)
def __str__(self): def __str__(self):
return self.render() return self.render()

View File

@ -4,7 +4,7 @@ from django.contrib.sites.models import Site
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.urlresolvers import reverse from django.urls import reverse
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from ponyconf.decorators import disable_for_loaddata from ponyconf.decorators import disable_for_loaddata

View File

@ -8,6 +8,6 @@
<h1>{% trans "Schedule" %}</h1> <h1>{% trans "Schedule" %}</h1>
{{ program }} {{ program|safe }}
{% endblock %} {% endblock %}

View File

@ -8,6 +8,6 @@
<h1>{% trans "Schedule" %}</h1> <h1>{% trans "Schedule" %}</h1>
{{ program }} {{ program|safe }}
{% endblock %} {% endblock %}

View File

@ -88,11 +88,11 @@
<p> <p>
<div class="btn-group" role="group" aria-label="vote"> <div class="btn-group" role="group" aria-label="vote">
<a class="btn {% if vote == -2 %} active {% endif %}btn-danger" href="{% url 'talk-vote' talk.pk '-2' %}">-2</a> <a class="btn {% if vote == -2 %} active {% endif %}btn-danger" href="{% url 'talk-vote' talk.pk -2 %}">-2</a>
<a class="btn {% if vote == -1 %} active {% endif %}btn-warning" href="{% url 'talk-vote' talk.pk '-1' %}">-1</a> <a class="btn {% if vote == -1 %} active {% endif %}btn-warning" href="{% url 'talk-vote' talk.pk -1 %}">-1</a>
<a class="btn {% if vote == 0 %} active {% endif %}btn-default" href="{% url 'talk-vote' talk.pk '0' %}"> 0</a> <a class="btn {% if vote == 0 %} active {% endif %}btn-default" href="{% url 'talk-vote' talk.pk 0 %}"> 0</a>
<a class="btn {% if vote == 1 %} active {% endif %}btn-info" href="{% url 'talk-vote' talk.pk '+1' %}">+1</a> <a class="btn {% if vote == 1 %} active {% endif %}btn-info" href="{% url 'talk-vote' talk.pk 1 %}">+1</a>
<a class="btn {% if vote == 2 %} active {% endif %}btn-success" href="{% url 'talk-vote' talk.pk '+2' %}">+2</a> <a class="btn {% if vote == 2 %} active {% endif %}btn-success" href="{% url 'talk-vote' talk.pk 2 %}">+2</a>
</div> </div>
</p> </p>
<p>{{ talk.vote_set.count }} {% trans "vote" %}{{ talk.vote_set.count|pluralize }}, {% trans "average:" %} {{ talk.score|floatformat:1 }}</p> <p>{{ talk.vote_set.count }} {% trans "vote" %}{{ talk.vote_set.count|pluralize }}, {% trans "average:" %} {{ talk.score|floatformat:1 }}</p>

View File

@ -1,6 +1,6 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse from django.urls import reverse
from django.test import TestCase from django.test import TestCase
from django.utils import timezone from django.utils import timezone
from django.contrib import messages from django.contrib import messages
@ -148,11 +148,12 @@ class ProposalTest(TestCase):
conf.home = '**Welcome!**' conf.home = '**Welcome!**'
conf.save() conf.save()
response = self.client.get(reverse('home')) response = self.client.get(reverse('home'))
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, '<strong>Welcome!</strong>') self.assertContains(response, '<strong>Welcome!</strong>')
def test_proposal_closed(self): def test_proposal_closed(self):
conf = Conference.objects.get(name='PonyConf') conf = Conference.objects.get(name='PonyConf')
Talk.objects.filter(site=conf.site).all().delete()
TalkCategory.objects.filter(site=conf.site).all().delete() TalkCategory.objects.filter(site=conf.site).all().delete()
response = self.client.get(reverse('proposal-home')) response = self.client.get(reverse('proposal-home'))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ -190,7 +191,7 @@ class ProposalTest(TestCase):
'description': 'PonyConf is cool.', 'description': 'PonyConf is cool.',
}) })
speaker = Participant.objects.get(site=site, name='Jean-Mi') speaker = Participant.objects.get(site=site, name='Jean-Mi')
self.assertEquals(speaker.email, 'jean-mi@example.org') self.assertEqual(speaker.email, 'jean-mi@example.org')
talk = Talk.objects.get(site=site, title='PonyConf') talk = Talk.objects.get(site=site, title='PonyConf')
self.assertRedirects(response, reverse('proposal-talk-details', kwargs=dict(speaker_token=speaker.token, talk_id=talk.pk)), 302) self.assertRedirects(response, reverse('proposal-talk-details', kwargs=dict(speaker_token=speaker.token, talk_id=talk.pk)), 302)
self.assertTrue(speaker in talk.speakers.all()) self.assertTrue(speaker in talk.speakers.all())
@ -211,9 +212,9 @@ class ProposalTest(TestCase):
'biography': 'New bio', 'biography': 'New bio',
}), reverse('proposal-dashboard', kwargs={'speaker_token': speaker.token})) }), reverse('proposal-dashboard', kwargs={'speaker_token': speaker.token}))
speaker = Participant.objects.get(pk=speaker.pk) speaker = Participant.objects.get(pk=speaker.pk)
self.assertEquals(speaker.name, 'New name') self.assertEqual(speaker.name, 'New name')
self.assertEquals(speaker.email, 'new-mail@example.org') self.assertEqual(speaker.email, 'new-mail@example.org')
self.assertEquals(speaker.biography, 'New bio') self.assertEqual(speaker.biography, 'New bio')
def test_proposal_talk_details(self): def test_proposal_talk_details(self):
speaker1 = Participant.objects.get(name='Speaker 1') speaker1 = Participant.objects.get(name='Speaker 1')
@ -235,7 +236,7 @@ class ProposalTest(TestCase):
'description': 'Talk description', 'description': 'Talk description',
}) })
talk = Talk.objects.get(title='New talk') talk = Talk.objects.get(title='New talk')
self.assertEquals(talk.description, 'Talk description') self.assertEqual(talk.description, 'Talk description')
self.assertRedirects(response, reverse('proposal-talk-details', kwargs=dict(speaker_token=speaker.token, talk_id=talk.pk))) self.assertRedirects(response, reverse('proposal-talk-details', kwargs=dict(speaker_token=speaker.token, talk_id=talk.pk)))
def test_proposal_talk_edit(self): def test_proposal_talk_edit(self):
@ -243,14 +244,14 @@ class ProposalTest(TestCase):
talk = Talk.objects.get(title='Talk 1') talk = Talk.objects.get(title='Talk 1')
url = reverse('proposal-talk-edit', kwargs={'speaker_token': speaker.token, 'talk_id': talk.pk}) url = reverse('proposal-talk-edit', kwargs={'speaker_token': speaker.token, 'talk_id': talk.pk})
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertRedirects(self.client.post(url, { self.assertRedirects(self.client.post(url, {
'title': 'New title', 'title': 'New title',
'description': 'New description', 'description': 'New description',
}), reverse('proposal-talk-details', kwargs=dict(speaker_token=speaker.token, talk_id=talk.pk))) }), reverse('proposal-talk-details', kwargs=dict(speaker_token=speaker.token, talk_id=talk.pk)))
talk = Talk.objects.get(pk=talk.pk) talk = Talk.objects.get(pk=talk.pk)
self.assertEquals(talk.title, 'New title') self.assertEqual(talk.title, 'New title')
self.assertEquals(talk.description, 'New description') self.assertEqual(talk.description, 'New description')
def test_proposal_speaker_add(self): def test_proposal_speaker_add(self):
speaker1 = Participant.objects.get(name='Speaker 1') speaker1 = Participant.objects.get(name='Speaker 1')
@ -271,13 +272,13 @@ class ProposalTest(TestCase):
'notify': 1, 'notify': 1,
}) })
self.assertRedirects(response, url_talk) self.assertRedirects(response, url_talk)
self.assertEquals(talk.speakers.count(), speaker_count+1) self.assertEqual(talk.speakers.count(), speaker_count+1)
speaker5 = Participant.objects.get(name='Speaker 5') speaker5 = Participant.objects.get(name='Speaker 5')
self.assertTrue(speaker5 in talk.speakers.all()) self.assertTrue(speaker5 in talk.speakers.all())
self.assertFalse(speaker4 in talk.speakers.all()) self.assertFalse(speaker4 in talk.speakers.all())
response = self.client.get(url_add_existing) response = self.client.get(url_add_existing)
self.assertRedirects(response, url_talk) self.assertRedirects(response, url_talk)
self.assertEquals(talk.speakers.count(), speaker_count+2) self.assertEqual(talk.speakers.count(), speaker_count+2)
self.assertTrue(speaker4 in talk.speakers.all()) self.assertTrue(speaker4 in talk.speakers.all())
@ -334,11 +335,11 @@ class ProposalTest(TestCase):
talk.accepted = None talk.accepted = None
talk.save() talk.save()
for url in [confirm_url, desist_url]: for url in [confirm_url, desist_url]:
self.assertEquals(self.client.get(url).status_code, 403) self.assertEqual(self.client.get(url).status_code, 403)
talk.accepted = False talk.accepted = False
talk.save() talk.save()
for url in [confirm_url, desist_url]: for url in [confirm_url, desist_url]:
self.assertEquals(self.client.get(url).status_code, 403) self.assertEqual(self.client.get(url).status_code, 403)
talk.accepted = True talk.accepted = True
talk.save() talk.save()
conf.save() conf.save()
@ -393,13 +394,13 @@ class StaffTest(TestCase):
url = reverse('staff') url = reverse('staff')
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
self.assertEquals(self.client.get(url).status_code, 200) self.assertEqual(self.client.get(url).status_code, 200)
def test_admin(self): def test_admin(self):
url = reverse('admin') url = reverse('admin')
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
self.assertEquals(self.client.get(url).status_code, 200) self.assertEqual(self.client.get(url).status_code, 200)
def test_volunteer_list(self): def test_volunteer_list(self):
url = reverse('volunteer-list') url = reverse('volunteer-list')
@ -431,14 +432,14 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_activity_add(self): def test_activity_add(self):
url = reverse('activity-list') url = reverse('activity-list')
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_activity_edit(self): def test_activity_edit(self):
conf = Conference.objects.get(name='PonyConf') conf = Conference.objects.get(name='PonyConf')
@ -446,13 +447,13 @@ class StaffTest(TestCase):
url = reverse('activity-edit', kwargs={'slug': activity.slug}) url = reverse('activity-edit', kwargs={'slug': activity.slug})
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
self.assertEquals(self.client.get(url).status_code, 200) self.assertEqual(self.client.get(url).status_code, 200)
response = self.client.post(url, { response = self.client.post(url, {
'name': 'New activity name', 'name': 'New activity name',
}) })
self.assertRedirects(response, reverse('activity-list')) self.assertRedirects(response, reverse('activity-list'))
activity = Activity.objects.get(pk=activity.pk) activity = Activity.objects.get(pk=activity.pk)
self.assertEquals(activity.name, 'New activity name') self.assertEqual(activity.name, 'New activity name')
def test_activity_remove(self): def test_activity_remove(self):
pass pass
@ -462,7 +463,7 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Speaker 1') self.assertContains(response, 'Speaker 1')
self.assertContains(response, 'Speaker 2') self.assertContains(response, 'Speaker 2')
response = self.client.get(url + '?format=csv') response = self.client.get(url + '?format=csv')
@ -478,7 +479,7 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Speaker 1') self.assertContains(response, 'Speaker 1')
self.assertContains(response, 'Speaker 2') self.assertContains(response, 'Speaker 2')
self.assertNotContains(response, 'Speaker 3') self.assertNotContains(response, 'Speaker 3')
@ -491,16 +492,16 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertRedirects(self.client.post(url, { self.assertRedirects(self.client.post(url, {
'name': 'New name', 'name': 'New name',
'email': 'new-mail@example.org', 'email': 'new-mail@example.org',
'biography': 'New bio', 'biography': 'New bio',
}), reverse('participant-details', kwargs={'participant_id': speaker.pk})) }), reverse('participant-details', kwargs={'participant_id': speaker.pk}))
speaker = Participant.objects.get(pk=speaker.pk) speaker = Participant.objects.get(pk=speaker.pk)
self.assertEquals(speaker.name, 'New name') self.assertEqual(speaker.name, 'New name')
self.assertEquals(speaker.email, 'new-mail@example.org') self.assertEqual(speaker.email, 'new-mail@example.org')
self.assertEquals(speaker.biography, 'New bio') self.assertEqual(speaker.biography, 'New bio')
def test_speaker_add_talk(self): def test_speaker_add_talk(self):
speaker = Participant.objects.get(name='Speaker 1') speaker = Participant.objects.get(name='Speaker 1')
@ -508,14 +509,14 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_talk_list(self): def test_talk_list(self):
url = reverse('talk-list') url = reverse('talk-list')
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Talk 1') self.assertContains(response, 'Talk 1')
response = self.client.get(url + '?format=csv') response = self.client.get(url + '?format=csv')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ -527,7 +528,7 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, talk.title) self.assertContains(response, talk.title)
def test_conference(self): def test_conference(self):
@ -536,7 +537,7 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_conference_opened_categories(self): def test_conference_opened_categories(self):
# TODO cover all cases # TODO cover all cases
@ -618,7 +619,7 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(accept_url), reverse('login') + '?next=' + accept_url) self.assertRedirects(self.client.get(accept_url), reverse('login') + '?next=' + accept_url)
self.assertRedirects(self.client.get(decline_url), reverse('login') + '?next=' + decline_url) self.assertRedirects(self.client.get(decline_url), reverse('login') + '?next=' + decline_url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
self.assertEquals(self.client.get(accept_url).status_code, 200) self.assertEqual(self.client.get(accept_url).status_code, 200)
self.assertRedirects(self.client.post(accept_url), details_url) self.assertRedirects(self.client.post(accept_url), details_url)
talk = Talk.objects.get(pk=talk.pk) talk = Talk.objects.get(pk=talk.pk)
self.assertTrue(talk.accepted) self.assertTrue(talk.accepted)
@ -627,7 +628,7 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.post(accept_url, {'message': 'Ok'}), details_url) self.assertRedirects(self.client.post(accept_url, {'message': 'Ok'}), details_url)
talk = Talk.objects.get(pk=talk.pk) talk = Talk.objects.get(pk=talk.pk)
self.assertTrue(talk.accepted) self.assertTrue(talk.accepted)
self.assertEquals(self.client.get(decline_url).status_code, 200) self.assertEqual(self.client.get(decline_url).status_code, 200)
self.assertRedirects(self.client.post(decline_url), details_url) self.assertRedirects(self.client.post(decline_url), details_url)
talk = Talk.objects.get(pk=talk.pk) talk = Talk.objects.get(pk=talk.pk)
self.assertFalse(talk.accepted) self.assertFalse(talk.accepted)
@ -648,50 +649,50 @@ class StaffTest(TestCase):
self.assertRedirects(self.client.get(confirm_url), reverse('login') + '?next=' + confirm_url) self.assertRedirects(self.client.get(confirm_url), reverse('login') + '?next=' + confirm_url)
self.assertRedirects(self.client.get(desist_url), reverse('login') + '?next=' + desist_url) self.assertRedirects(self.client.get(desist_url), reverse('login') + '?next=' + desist_url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
self.assertEquals(self.client.get(confirm_url).status_code, 403) self.assertEqual(self.client.get(confirm_url).status_code, 403)
self.assertEquals(self.client.get(desist_url).status_code, 403) self.assertEqual(self.client.get(desist_url).status_code, 403)
talk.accepted = False talk.accepted = False
talk.save() talk.save()
self.assertEquals(self.client.get(confirm_url).status_code, 403) self.assertEqual(self.client.get(confirm_url).status_code, 403)
self.assertEquals(self.client.get(desist_url).status_code, 403) self.assertEqual(self.client.get(desist_url).status_code, 403)
talk.accepted = True talk.accepted = True
talk.save() talk.save()
self.assertRedirects(self.client.get(confirm_url), details_url) self.assertRedirects(self.client.get(confirm_url), details_url)
talk = Talk.objects.get(pk=talk.pk) talk = Talk.objects.get(pk=talk.pk)
self.assertTrue(talk.confirmed) self.assertTrue(talk.confirmed)
self.assertEquals(self.client.get(confirm_url).status_code, 403) self.assertEqual(self.client.get(confirm_url).status_code, 403)
self.assertRedirects(self.client.get(desist_url), details_url) self.assertRedirects(self.client.get(desist_url), details_url)
talk = Talk.objects.get(pk=talk.pk) talk = Talk.objects.get(pk=talk.pk)
self.assertFalse(talk.confirmed) self.assertFalse(talk.confirmed)
self.assertEquals(self.client.get(desist_url).status_code, 403) self.assertEqual(self.client.get(desist_url).status_code, 403)
def test_category_list(self): def test_category_list(self):
url = reverse('category-list') url = reverse('category-list')
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_category_add(self): def test_category_add(self):
url = reverse('category-add') url = reverse('category-add')
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_tag_list(self): def test_tag_list(self):
url = reverse('tag-list') url = reverse('tag-list')
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_tag_add(self): def test_tag_add(self):
url = reverse('tag-add') url = reverse('tag-add')
self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url) self.assertRedirects(self.client.get(url), reverse('login') + '?next=' + url)
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(url) response = self.client.get(url)
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
class ScheduleTest(TestCase): class ScheduleTest(TestCase):
@ -719,10 +720,10 @@ class ScheduleTest(TestCase):
def test_public_schedule(self): def test_public_schedule(self):
site = Site.objects.first() site = Site.objects.first()
conf = Conference.objects.get(site=site) conf = Conference.objects.get(site=site)
self.assertEquals(self.client.get(reverse('public-schedule')).status_code, 403) self.assertEqual(self.client.get(reverse('public-schedule')).status_code, 403)
conf.schedule_publishing_date = timezone.now() - timedelta(hours=1) conf.schedule_publishing_date = timezone.now() - timedelta(hours=1)
conf.save() conf.save()
self.assertEquals(self.client.get(reverse('public-schedule')).status_code, 200) self.assertEqual(self.client.get(reverse('public-schedule')).status_code, 200)
conf.schedule_redirection_url ='http://example.net/schedule.html' conf.schedule_redirection_url ='http://example.net/schedule.html'
conf.save() conf.save()
self.assertRedirects(self.client.get(reverse('public-schedule')), conf.schedule_redirection_url, status_code=302, fetch_redirect_response=False) self.assertRedirects(self.client.get(reverse('public-schedule')), conf.schedule_redirection_url, status_code=302, fetch_redirect_response=False)
@ -735,7 +736,7 @@ class ScheduleTest(TestCase):
def test_xml(self): def test_xml(self):
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(reverse('staff-schedule') + 'xml/') response = self.client.get(reverse('staff-schedule') + 'xml/')
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Public tag') self.assertContains(response, 'Public tag')
self.assertNotContains(response, 'Private tag') self.assertNotContains(response, 'Private tag')
ET.fromstring(response.content) ET.fromstring(response.content)
@ -743,7 +744,7 @@ class ScheduleTest(TestCase):
def test_ics(self): def test_ics(self):
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
response = self.client.get(reverse('staff-schedule') + 'ics/') response = self.client.get(reverse('staff-schedule') + 'ics/')
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
Calendar.from_ical(response.content) Calendar.from_ical(response.content)
def test_html(self): def test_html(self):
@ -751,8 +752,8 @@ class ScheduleTest(TestCase):
response = self.client.get(reverse('staff-schedule') + 'html/') response = self.client.get(reverse('staff-schedule') + 'html/')
self.assertContains(response, 'Staff tag') self.assertContains(response, 'Staff tag')
self.assertNotContains(response, 'Not staff tag') self.assertNotContains(response, 'Not staff tag')
self.assertEquals(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_inexistent_format(self): def test_inexistent_format(self):
self.client.login(username='admin', password='admin') self.client.login(username='admin', password='admin')
self.assertEquals(self.client.get(reverse('staff-schedule') + 'inexistent/').status_code, 404) self.assertEqual(self.client.get(reverse('staff-schedule') + 'inexistent/').status_code, 404)

View File

@ -1,70 +1,71 @@
from django.conf.urls import url from django.urls import path, re_path, register_converter
from . import views, converters
register_converter(converters.SignedIntConverter, 'sint')
from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.home, name='home'), path('', views.home, name='home'),
# v1.1 path('cfp/', views.proposal_home, name='proposal-home'),
url(r'^cfp/$', views.proposal_home, name='proposal-home'), path('cfp/token/', views.proposal_mail_token, name='proposal-mail-token'),
url(r'^cfp/token/$', views.proposal_mail_token, name='proposal-mail-token'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?dashboard/$', views.proposal_dashboard, name='proposal-dashboard'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?dashboard/$', views.proposal_dashboard, name='proposal-dashboard'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?profile/$', views.proposal_speaker_edit, name='proposal-profile-edit'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?profile/$', views.proposal_speaker_edit, name='proposal-profile-edit'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/add/$', views.proposal_talk_edit, name='proposal-talk-add'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/add/$', views.proposal_talk_edit, name='proposal-talk-add'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/$', views.proposal_talk_details, name='proposal-talk-details'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/$', views.proposal_talk_details, name='proposal-talk-details'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/edit/$', views.proposal_talk_edit, name='proposal-talk-edit'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/edit/$', views.proposal_talk_edit, name='proposal-talk-edit'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/speaker/add/$', views.proposal_speaker_edit, name='proposal-speaker-add'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/speaker/add/$', views.proposal_speaker_edit, name='proposal-speaker-add'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/speaker/add/(?P<speaker_id>[0-9]+)/$', views.proposal_speaker_add, name='proposal-speaker-add-existing'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/speaker/add/(?P<speaker_id>[0-9]+)/$', views.proposal_speaker_add, name='proposal-speaker-add-existing'), #re_path(r'^cfp(?:/(?P<speaker_token>[\w\-]+))?/talk/(?P<talk_id>[0-9]+)/speaker/(?P<co_speaker_id>[0-9]+)/$', views.proposal_speaker_details, name='proposal-speaker-details'),
#url(r'^cfp(?:/(?P<speaker_token>[\w\-]+))?/talk/(?P<talk_id>[0-9]+)/speaker/(?P<co_speaker_id>[0-9]+)/$', views.proposal_speaker_details, name='proposal-speaker-details'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/speaker/(?P<co_speaker_id>[0-9]+)/edit/$', views.proposal_speaker_edit, name='proposal-speaker-edit'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/speaker/(?P<co_speaker_id>[0-9]+)/edit/$', views.proposal_speaker_edit, name='proposal-speaker-edit'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/speaker/(?P<co_speaker_id>[0-9]+)/remove/$', views.proposal_speaker_remove, name='proposal-speaker-remove'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/speaker/(?P<co_speaker_id>[0-9]+)/remove/$', views.proposal_speaker_remove, name='proposal-speaker-remove'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/confirm/$', views.proposal_talk_acknowledgment, {'confirm': True}, name='proposal-talk-confirm'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/confirm/$', views.proposal_talk_acknowledgment, {'confirm': True}, name='proposal-talk-confirm'), re_path(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/desist/$', views.proposal_talk_acknowledgment, {'confirm': False}, name='proposal-talk-desist'),
url(r'^cfp/(?:(?P<speaker_token>[\w\-]+)/)?talk/(?P<talk_id>[0-9]+)/desist/$', views.proposal_talk_acknowledgment, {'confirm': False}, name='proposal-talk-desist'), path('volunteer/enrole', views.volunteer_enrole, name='volunteer-enrole'),
url(r'^volunteer/enrole/$', views.volunteer_enrole, name='volunteer-enrole'), path('volunteer/token/', views.volunteer_mail_token, name='volunteer-mail-token'),
url(r'^volunteer/token/$', views.volunteer_mail_token, name='volunteer-mail-token'), re_path(r'^volunteer/(?:(?P<volunteer_token>[\w\-]+)/)?$', views.volunteer_dashboard, name='volunteer-dashboard'),
url(r'^volunteer/(?:(?P<volunteer_token>[\w\-]+)/)?$', views.volunteer_dashboard, name='volunteer-dashboard'), re_path(r'^volunteer/(?:(?P<volunteer_token>[\w\-]+)/)?profile/$', views.volunteer_profile, name='volunteer-profile-edit'),
url(r'^volunteer/(?:(?P<volunteer_token>[\w\-]+)/)?profile/$', views.volunteer_profile, name='volunteer-profile-edit'), re_path(r'^volunteer/(?:(?P<volunteer_token>[\w\-]+)/)?join/(?P<activity>[\w\-]+)/$', views.volunteer_update_activity, {'join': True}, name='volunteer-join'),
url(r'^volunteer/(?:(?P<volunteer_token>[\w\-]+)/)?join/(?P<activity>[\w\-]+)/$', views.volunteer_update_activity, {'join': True}, name='volunteer-join'), re_path(r'^volunteer/(?:(?P<volunteer_token>[\w\-]+)/)?quit/(?P<activity>[\w\-]+)/$', views.volunteer_update_activity, {'join': False}, name='volunteer-quit'),
url(r'^volunteer/(?:(?P<volunteer_token>[\w\-]+)/)?quit/(?P<activity>[\w\-]+)/$', views.volunteer_update_activity, {'join': False}, name='volunteer-quit'), path('staff/', views.staff, name='staff'),
#url(r'^talk/(?P<talk_id>[\w\-]+)/$', views.talk_show, name='show-talk'), path('staff/talks/', views.talk_list, name='talk-list'),
#url(r'^speaker/(?P<participant_id>[\w\-]+)/$', views.speaker_show, name='show-speaker'), path('staff/talks/<int:talk_id>/', views.talk_details, name='talk-details'),
url(r'^staff/$', views.staff, name='staff'), path('staff/talks/<int:talk_id>/vote/<sint:score>/', views.talk_vote, name='talk-vote'),
url(r'^staff/talks/$', views.talk_list, name='talk-list'), path('staff/talks/<int:talk_id>/accept/', views.talk_decide, {'accept': True}, name='talk-accept'),
url(r'^staff/talks/(?P<talk_id>[0-9]+)/$', views.talk_details, name='talk-details'), path('staff/talks/<int:talk_id>/decline/', views.talk_decide, {'accept': False}, name='talk-decline'),
url(r'^staff/talks/(?P<talk_id>[0-9]+)/vote/(?P<score>[-+0-2]+)/$', views.talk_vote, name='talk-vote'), path('staff/talks/<int:talk_id>/confirm/', views.talk_acknowledgment, {'confirm': True}, name='talk-confirm-by-staff'),
url(r'^staff/talks/(?P<talk_id>[0-9]+)/accept/$', views.talk_decide, {'accept': True}, name='talk-accept'), path('staff/talks/<int:talk_id>/desist/', views.talk_acknowledgment, {'confirm': False}, name='talk-desist-by-staff'),
url(r'^staff/talks/(?P<talk_id>[0-9]+)/decline/$', views.talk_decide, {'accept': False}, name='talk-decline'), path('staff/talks/<int:talk_id>/edit/', views.TalkUpdate.as_view(), name='talk-edit'),
url(r'^staff/talks/(?P<talk_id>[0-9]+)/confirm/$', views.talk_acknowledgment, {'confirm': True}, name='talk-confirm-by-staff'), path('staff/speakers/', views.participant_list, name='participant-list'),
url(r'^staff/talks/(?P<talk_id>[0-9]+)/desist/$', views.talk_acknowledgment, {'confirm': False}, name='talk-desist-by-staff'), path('staff/speakers/add/', views.ParticipantCreate.as_view(), name='participant-add'),
url(r'^staff/talks/(?P<talk_id>[0-9]+)/edit/$', views.TalkUpdate.as_view(), name='talk-edit'), path('staff/speakers/<int:participant_id>/', views.participant_details, name='participant-details'),
url(r'^staff/speakers/$', views.participant_list, name='participant-list'), path('staff/speakers/<int:participant_id>/add-talk/', views.participant_add_talk, name='participant-add-talk'),
url(r'^staff/speakers/add/$', views.ParticipantCreate.as_view(), name='participant-add'), path('staff/speakers/<int:participant_id>/edit/', views.ParticipantUpdate.as_view(), name='participant-edit'),
url(r'^staff/speakers/(?P<participant_id>[0-9]+)/$', views.participant_details, name='participant-details'), path('staff/speakers/<int:participant_id>/remove/', views.ParticipantRemove.as_view(), name='participant-remove'),
url(r'^staff/speakers/(?P<participant_id>[0-9]+)/add-talk/$', views.participant_add_talk, name='participant-add-talk'), path('staff/tracks/', views.TrackList.as_view(), name='track-list'),
url(r'^staff/speakers/(?P<participant_id>[0-9]+)/edit/$', views.ParticipantUpdate.as_view(), name='participant-edit'), path('staff/tracks/add/', views.TrackCreate.as_view(), name='track-add'),
url(r'^staff/speakers/(?P<participant_id>[0-9]+)/remove/$', views.ParticipantRemove.as_view(), name='participant-remove'), path('staff/tracks/<slug:slug>/edit/', views.TrackUpdate.as_view(), name='track-edit'),
url(r'^staff/tracks/$', views.TrackList.as_view(), name='track-list'), path('staff/rooms/', views.RoomList.as_view(), name='room-list'),
url(r'^staff/tracks/add/$', views.TrackCreate.as_view(), name='track-add'), path('staff/rooms/add/', views.RoomCreate.as_view(), name='room-add'),
url(r'^staff/tracks/(?P<slug>[-\w]+)/edit/$', views.TrackUpdate.as_view(), name='track-edit'), path('staff/rooms/<slug:slug>/', views.RoomDetail.as_view(), name='room-details'),
url(r'^staff/rooms/$', views.RoomList.as_view(), name='room-list'), path('staff/rooms/<slug:slug>/edit/', views.RoomUpdate.as_view(), name='room-edit'),
url(r'^staff/rooms/add/$', views.RoomCreate.as_view(), name='room-add'), path('staff/volunteers/', views.volunteer_list, name='volunteer-list'),
url(r'^staff/rooms/(?P<slug>[-\w]+)/$', views.RoomDetail.as_view(), name='room-details'), path('staff/volunteers/<int:volunteer_id>/', views.volunteer_details, name='volunteer-details'),
url(r'^staff/rooms/(?P<slug>[-\w]+)/edit/$', views.RoomUpdate.as_view(), name='room-edit'), path('staff/add-user/', views.create_user, name='create-user'),
url(r'^staff/volunteers/$', views.volunteer_list, name='volunteer-list'), re_path(r'^staff/schedule/((?P<program_format>[\w]+)/)?$', views.staff_schedule, name='staff-schedule'),
url(r'^staff/volunteers/(?P<volunteer_id>[\w\-]+)/$', views.volunteer_details, name='volunteer-details'), path('staff/select2/', views.Select2View.as_view(), name='django_select2-json'),
url(r'^staff/add-user/$', views.create_user, name='create-user'), path('admin/', views.admin, name='admin'),
url(r'^staff/schedule/((?P<program_format>[\w]+)/)?$', views.staff_schedule, name='staff-schedule'), path('admin/conference/', views.conference_edit, name='conference-edit'),
url(r'^staff/select2/$', views.Select2View.as_view(), name='django_select2-json'), path('admin/homepage/', views.homepage_edit, name='homepage-edit'),
url(r'^admin/$', views.admin, name='admin'), path('admin/categories/', views.TalkCategoryList.as_view(), name='category-list'),
url(r'^admin/conference/$', views.conference_edit, name='conference-edit'), path('admin/categories/add/', views.TalkCategoryCreate.as_view(), name='category-add'),
url(r'^admin/homepage/$', views.homepage_edit, name='homepage-edit'), path('admin/categories/<int:pk>/edit/', views.TalkCategoryUpdate.as_view(), name='category-edit'),
url(r'^admin/categories/$', views.TalkCategoryList.as_view(), name='category-list'), path('admin/tags/', views.TagList.as_view(), name='tag-list'),
url(r'^admin/categories/add/$', views.TalkCategoryCreate.as_view(), name='category-add'), path('admin/tags/add/', views.TagCreate.as_view(), name='tag-add'),
url(r'^admin/categories/(?P<pk>[0-9]+)/edit/$', views.TalkCategoryUpdate.as_view(), name='category-edit'), path('admin/tags/<slug:slug>/edit/', views.TagUpdate.as_view(), name='tag-edit'),
url(r'^admin/tags/$', views.TagList.as_view(), name='tag-list'), path('admin/activities/', views.ActivityList.as_view(), name='activity-list'),
url(r'^admin/tags/add/$', views.TagCreate.as_view(), name='tag-add'), path('admin/activities/add/', views.ActivityCreate.as_view(), name='activity-add'),
url(r'^admin/tags/(?P<slug>[-\w]+)/edit/$', views.TagUpdate.as_view(), name='tag-edit'), path('admin/activities/<slug:slug>/edit/', views.ActivityUpdate.as_view(), name='activity-edit'),
url(r'^admin/activities/$', views.ActivityList.as_view(), name='activity-list'), re_path(r'^schedule/((?P<program_format>[\w]+)/)?$', views.public_schedule, name='public-schedule'),
url(r'^admin/activities/add/$', views.ActivityCreate.as_view(), name='activity-add'),
url(r'^admin/activities/(?P<slug>[-\w]+)/edit/$', views.ActivityUpdate.as_view(), name='activity-edit'),
url(r'^schedule/((?P<program_format>[\w]+)/)?$', views.public_schedule, name='public-schedule'),
] ]

View File

@ -1,8 +1,7 @@
from django.core.mail import send_mail from django.core.mail import send_mail
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.urls import reverse from django.urls import reverse, reverse_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic import DeleteView, FormView, TemplateView from django.views.generic import DeleteView, FormView, TemplateView
from django.contrib import messages from django.contrib import messages
@ -42,24 +41,24 @@ def home(request):
def volunteer_enrole(request): def volunteer_enrole(request):
if request.user.is_authenticated() and Volunteer.objects.filter(site=request.conference.site, email=request.user.email).exists(): if request.user.is_authenticated and Volunteer.objects.filter(site=request.conference.site, email=request.user.email).exists():
return redirect(reverse('volunteer-dashboard')) return redirect(reverse('volunteer-dashboard'))
if not request.conference.volunteers_enrollment_is_open(): if not request.conference.volunteers_enrollment_is_open():
raise PermissionDenied raise PermissionDenied
initial = {} initial = {}
if request.user.is_authenticated() and not request.POST: if request.user.is_authenticated and not request.POST:
initial.update({ initial.update({
'name': request.user.get_full_name(), 'name': request.user.get_full_name(),
'phone_number': request.user.profile.phone_number, 'phone_number': request.user.profile.phone_number,
'sms_prefered': request.user.profile.sms_prefered, 'sms_prefered': request.user.profile.sms_prefered,
}) })
form = VolunteerForm(request.POST or None, initial=initial, conference=request.conference) form = VolunteerForm(request.POST or None, initial=initial, conference=request.conference)
if request.user.is_authenticated(): if request.user.is_authenticated:
form.fields.pop('email') form.fields.pop('email')
if request.method == 'POST' and form.is_valid(): if request.method == 'POST' and form.is_valid():
volunteer = form.save(commit=False) volunteer = form.save(commit=False)
volunteer.language = request.LANGUAGE_CODE volunteer.language = request.LANGUAGE_CODE
if request.user.is_authenticated(): if request.user.is_authenticated:
volunteer.email = request.user.email volunteer.email = request.user.email
volunteer.save() volunteer.save()
form.save_m2m() form.save_m2m()
@ -205,7 +204,7 @@ def proposal_home(request):
return render(request, 'cfp/closed.html') return render(request, 'cfp/closed.html')
initial = {} initial = {}
fields = ['name', 'email', 'biography'] fields = ['name', 'email', 'biography']
if request.user.is_authenticated(): if request.user.is_authenticated:
if Participant.objects.filter(site=request.conference.site, email=request.user.email).exists(): if Participant.objects.filter(site=request.conference.site, email=request.user.email).exists():
return redirect(reverse('proposal-dashboard')) return redirect(reverse('proposal-dashboard'))
elif not request.POST: elif not request.POST:
@ -220,7 +219,7 @@ def proposal_home(request):
if request.method == 'POST' and all(map(lambda f: f.is_valid(), [speaker_form, talk_form])): if request.method == 'POST' and all(map(lambda f: f.is_valid(), [speaker_form, talk_form])):
speaker = speaker_form.save(commit=False) speaker = speaker_form.save(commit=False)
speaker.site = request.conference.site speaker.site = request.conference.site
if request.user.is_authenticated(): if request.user.is_authenticated:
speaker.email = request.user.email speaker.email = request.user.email
speaker.save() speaker.save()
talk = talk_form.save(commit=False) talk = talk_form.save(commit=False)
@ -725,9 +724,11 @@ def talk_details(request, talk_id):
@staff_required @staff_required
def talk_vote(request, talk_id, score): def talk_vote(request, talk_id, score):
if score not in [-2, -1, 0, 1, 2]:
raise Http404
talk = get_object_or_404(Talk, pk=talk_id, site=request.conference.site) talk = get_object_or_404(Talk, pk=talk_id, site=request.conference.site)
vote, created = Vote.objects.get_or_create(talk=talk, user=request.user) vote, created = Vote.objects.get_or_create(talk=talk, user=request.user)
vote.vote = int(score) vote.vote = score
vote.save() vote.save()
messages.success(request, _('Vote successfully created') if created else _('Vote successfully updated')) messages.success(request, _('Vote successfully created') if created else _('Vote successfully updated'))
return redirect(talk.get_absolute_url()) return redirect(talk.get_absolute_url())

View File

@ -56,9 +56,9 @@ class MessageManager(models.Manager):
class Message(models.Model): class Message(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
thread = models.ForeignKey(MessageThread) thread = models.ForeignKey(MessageThread, on_delete=models.CASCADE)
author = models.ForeignKey(MessageAuthor) author = models.ForeignKey(MessageAuthor, on_delete=models.PROTECT)
in_reply_to = models.ForeignKey('self', null=True, blank=True) in_reply_to = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL)
subject = models.CharField(max_length=1000, blank=True) subject = models.CharField(max_length=1000, blank=True)
content = models.TextField(blank=True) content = models.TextField(blank=True)
token = models.CharField(max_length=64, default=generate_message_token, unique=True) token = models.CharField(max_length=64, default=generate_message_token, unique=True)

View File

@ -1,6 +1,6 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse from django.urls import reverse
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from django.core import mail from django.core import mail
from django.conf import settings from django.conf import settings

View File

@ -66,7 +66,6 @@ MIDDLEWARE = [
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',

View File

@ -1,19 +1,4 @@
"""ponyconf URL Configuration from django.urls import include, path
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import include, url
from django.contrib import admin from django.contrib import admin
from django.conf import settings from django.conf import settings
@ -21,14 +6,14 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^markdown/$', views.markdown_preview, name='markdown-preview'), path('markdown/', views.markdown_preview, name='markdown-preview'),
url(r'^admin/django/', admin.site.urls), path('admin/django/', admin.site.urls),
url(r'^accounts/', include('accounts.urls')), path('accounts/', include('accounts.urls')),
url(r'^', include('cfp.urls')), path('', include('cfp.urls')),
] ]
if settings.DEBUG and 'debug_toolbar' in settings.INSTALLED_APPS: if settings.DEBUG and 'debug_toolbar' in settings.INSTALLED_APPS:
import debug_toolbar import debug_toolbar
urlpatterns += [ urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)), path('__debug__/', include(debug_toolbar.urls)),
] ]

View File

@ -1,11 +1,11 @@
django<1.12 django<3
django-autoslug
django-bootstrap3 django-bootstrap3
django-bower django-bower
django-crispy-forms django-crispy-forms
django-select2<6 django-select2<6
django-colorful django-colorful
-e git://github.com/nim65s/django-autoslug.git#egg=django-autoslug
markdown markdown
bleach bleach

View File

@ -4,19 +4,19 @@
# #
# pip-compile --output-file requirements.txt requirements.in # pip-compile --output-file requirements.txt requirements.in
# #
bleach==2.1.1 -e git+git://github.com/nim65s/django-autoslug.git#egg=django-autoslug
bleach==2.1.2
chardet==3.0.4 chardet==3.0.4
django-appconf==1.0.2 # via django-select2 django-appconf==1.0.2 # via django-select2
django-autoslug==1.9.3
django-bootstrap3==9.1.0 django-bootstrap3==9.1.0
django-bower==5.2.0 django-bower==5.2.0
django-colorful==1.2 django-colorful==1.2
django-crispy-forms==1.7.0 django-crispy-forms==1.7.0
django-select2==5.11.1 django-select2==5.11.1
django==1.11.7 django==2.0
html5lib==1.0b10 # via bleach html5lib==1.0.1 # via bleach
icalendar==4.0.0 icalendar==4.0.0
markdown==2.6.9 markdown==2.6.10
python-dateutil==2.6.1 # via icalendar python-dateutil==2.6.1 # via icalendar
pytz==2017.3 # via django, icalendar pytz==2017.3 # via django, icalendar
six==1.11.0 # via bleach, django-bower, html5lib, python-dateutil six==1.11.0 # via bleach, django-bower, html5lib, python-dateutil