sortedm2m, remove Speech, reset migrations

BREAK ALL THE THINGS \o/
This commit is contained in:
Guilhem Saurel 2016-06-30 01:02:00 +02:00
parent fa7c943b3f
commit 3d9d9a554b
25 changed files with 100 additions and 467 deletions

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-15 09:49 # Generated by Django 1.9.7 on 2016-06-29 22:03
from __future__ import unicode_literals from __future__ import unicode_literals
import accounts.utils import accounts.utils
@ -16,6 +16,7 @@ class Migration(migrations.Migration):
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('sites', '0002_alter_domain_unique'),
] ]
operations = [ operations = [
@ -23,11 +24,17 @@ class Migration(migrations.Migration):
name='Participation', name='Participation',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('arrival', models.DateTimeField(blank=True, null=True)), ('arrival', models.DateTimeField(blank=True, null=True)),
('departure', models.DateTimeField(blank=True, null=True)), ('departure', models.DateTimeField(blank=True, null=True)),
('transport', models.IntegerField(blank=True, choices=[(1, 'train'), (2, 'plane')], null=True)), ('transport', models.IntegerField(blank=True, choices=[(1, 'train'), (2, 'plane'), (3, 'others')], null=True)),
('connector', models.IntegerField(blank=True, choices=[(1, 'VGA'), (2, 'HDMI'), (3, 'miniDP')], null=True)), ('connector', models.IntegerField(blank=True, choices=[(1, 'VGA'), (2, 'HDMI'), (3, 'miniDP')], null=True)),
('constraints', models.TextField(blank=True)), ('constraints', models.TextField(blank=True)),
('sound', models.BooleanField(default=False, verbose_name='I need sound')),
('orga', models.BooleanField(default=False)),
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
], ],
managers=[ managers=[
('objects', django.db.models.manager.Manager()), ('objects', django.db.models.manager.Manager()),
@ -38,9 +45,19 @@ class Migration(migrations.Migration):
name='Profile', name='Profile',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('biography', models.TextField(blank=True, verbose_name='Biography')), ('biography', models.TextField(blank=True, verbose_name='Biography')),
('email_token', models.CharField(default=accounts.utils.generate_user_uid, max_length=12)), ('email_token', models.CharField(default=accounts.utils.generate_user_uid, max_length=12, unique=True)),
('notes', models.TextField(default='')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
], ],
options={
'abstract': False,
},
),
migrations.AlterUniqueTogether(
name='participation',
unique_together=set([('site', 'user')]),
), ),
] ]

View File

@ -1,41 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-15 09:49
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('proposals', '0001_initial'),
('sites', '0002_alter_domain_unique'),
('accounts', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='participation',
name='review_topics',
field=models.ManyToManyField(blank=True, to='proposals.Topic'),
),
migrations.AddField(
model_name='participation',
name='site',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.Site'),
),
migrations.AddField(
model_name='participation',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterUniqueTogether(
name='participation',
unique_together=set([('site', 'user')]),
),
]

View File

@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-15 20:31
from __future__ import unicode_literals
import accounts.utils
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0002_auto_20160615_0949'),
]
operations = [
migrations.AlterField(
model_name='participation',
name='transport',
field=models.IntegerField(blank=True, choices=[(1, 'train'), (2, 'plane'), (3, 'others')], null=True),
),
migrations.AlterField(
model_name='profile',
name='email_token',
field=models.CharField(default=accounts.utils.generate_user_uid, max_length=12, unique=True),
),
]

View File

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-19 20:26
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0003_auto_20160615_2031'),
]
operations = [
migrations.RemoveField(
model_name='participation',
name='review_topics',
),
]

View File

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-25 10:38
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0004_remove_participation_review_topics'),
]
operations = [
migrations.AddField(
model_name='participation',
name='sound',
field=models.BooleanField(default=False, verbose_name='I need sound'),
),
]

View File

@ -1,41 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-25 11:37
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('accounts', '0005_participation_sound'),
]
operations = [
migrations.AddField(
model_name='participation',
name='created',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 6, 25, 11, 37, 1, 575397, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='participation',
name='updated',
field=models.DateTimeField(auto_now=True, default=datetime.datetime(2016, 6, 25, 11, 37, 5, 56658, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='profile',
name='created',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 6, 25, 11, 37, 6, 538667, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='profile',
name='updated',
field=models.DateTimeField(auto_now=True, default=datetime.datetime(2016, 6, 25, 11, 37, 7, 804703, tzinfo=utc)),
preserve_default=False,
),
]

View File

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-25 14:37
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0006_auto_20160625_1137'),
]
operations = [
migrations.AddField(
model_name='participation',
name='orga',
field=models.BooleanField(default=False),
),
]

View File

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-25 15:03
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0007_participation_orga'),
]
operations = [
migrations.AddField(
model_name='profile',
name='notes',
field=models.TextField(default=''),
),
]

View File

@ -42,9 +42,21 @@ class AccountTests(TestCase):
self.client.logout() self.client.logout()
def test_participant_views(self): def test_participant_views(self):
self.assertEqual(self.client.get(reverse('register')).status_code, 200)
self.client.login(username='b', password='b') self.client.login(username='b', password='b')
self.assertEqual(self.client.get(reverse('list-participant')).status_code, 302) self.assertEqual(self.client.get(reverse('list-participant')).status_code, 302)
b = User.objects.get(username='b') b = User.objects.get(username='b')
b.is_superuser = True b.is_superuser = True
b.save() b.save()
self.assertEqual(self.client.get(reverse('list-participant')).status_code, 200) self.assertEqual(self.client.get(reverse('list-participant')).status_code, 200)
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
{'biography': 'foo', 'notes': 'bar'}).status_code, 403)
b = Participation.on_site.get(user=b)
b.orga = True
b.save()
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
{'biography': 'foo', 'nootes': 'bar'}).status_code, 200)
self.assertEqual(User.objects.get(username='a').profile.biography, '')
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
{'biography': 'foo', 'notes': 'bar'}).status_code, 200)
self.assertEqual(User.objects.get(username='a').profile.biography, 'foo')

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-15 09:49 # Generated by Django 1.9.7 on 2016-06-29 22:04
from __future__ import unicode_literals from __future__ import unicode_literals
import conversations.utils import conversations.utils
@ -14,6 +14,7 @@ class Migration(migrations.Migration):
dependencies = [ dependencies = [
('accounts', '0001_initial'), ('accounts', '0001_initial'),
('proposals', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'), ('contenttypes', '0002_remove_content_type_name'),
] ]
@ -23,7 +24,10 @@ class Migration(migrations.Migration):
name='ConversationAboutTalk', name='ConversationAboutTalk',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('subscribers', models.ManyToManyField(blank=True, related_name='_conversationabouttalk_subscribers_+', to=settings.AUTH_USER_MODEL)), ('subscribers', models.ManyToManyField(blank=True, related_name='_conversationabouttalk_subscribers_+', to=settings.AUTH_USER_MODEL)),
('talk', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='conversation', to='proposals.Talk')),
], ],
options={ options={
'abstract': False, 'abstract': False,
@ -33,6 +37,8 @@ class Migration(migrations.Migration):
name='ConversationWithParticipant', name='ConversationWithParticipant',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('participation', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='conversation', to='accounts.Participation')), ('participation', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='conversation', to='accounts.Participation')),
('subscribers', models.ManyToManyField(blank=True, related_name='_conversationwithparticipant_subscribers_+', to=settings.AUTH_USER_MODEL)), ('subscribers', models.ManyToManyField(blank=True, related_name='_conversationwithparticipant_subscribers_+', to=settings.AUTH_USER_MODEL)),
], ],
@ -44,15 +50,16 @@ class Migration(migrations.Migration):
name='Message', name='Message',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('object_id', models.PositiveIntegerField()), ('object_id', models.PositiveIntegerField()),
('token', models.CharField(default=conversations.utils.generate_message_token, max_length=64)), ('token', models.CharField(default=conversations.utils.generate_message_token, max_length=64, unique=True)),
('date', models.DateTimeField(auto_now_add=True)),
('content', models.TextField()), ('content', models.TextField()),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
], ],
options={ options={
'ordering': ['date'], 'ordering': ['created'],
}, },
), ),
] ]

View File

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-15 09:49
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('proposals', '0001_initial'),
('conversations', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='conversationabouttalk',
name='talk',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='conversation', to='proposals.Talk'),
),
]

View File

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-15 20:31
from __future__ import unicode_literals
import conversations.utils
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('conversations', '0002_conversationabouttalk_talk'),
]
operations = [
migrations.AlterField(
model_name='message',
name='token',
field=models.CharField(default=conversations.utils.generate_message_token, max_length=64, unique=True),
),
]

View File

@ -1,56 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-25 11:37
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('conversations', '0003_auto_20160615_2031'),
]
operations = [
migrations.AlterModelOptions(
name='message',
options={'ordering': ['created']},
),
migrations.RenameField(
model_name='message',
old_name='date',
new_name='created',
),
migrations.AddField(
model_name='conversationabouttalk',
name='created',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 6, 25, 11, 37, 10, 600649, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='conversationabouttalk',
name='updated',
field=models.DateTimeField(auto_now=True, default=datetime.datetime(2016, 6, 25, 11, 37, 12, 58625, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='conversationwithparticipant',
name='created',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 6, 25, 11, 37, 13, 178710, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='conversationwithparticipant',
name='updated',
field=models.DateTimeField(auto_now=True, default=datetime.datetime(2016, 6, 25, 11, 37, 14, 346657, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='message',
name='updated',
field=models.DateTimeField(auto_now=True, default=datetime.datetime(2016, 6, 25, 11, 37, 15, 482594, tzinfo=utc)),
preserve_default=False,
),
]

View File

@ -41,6 +41,7 @@ INSTALLED_APPS = [
'djangobower', 'djangobower',
'bootstrap3', 'bootstrap3',
'registration', 'registration',
'sortedm2m',
# build-in apps # build-in apps
'django.contrib.admin', 'django.contrib.admin',

View File

@ -1,7 +1,6 @@
from django.contrib import admin from django.contrib import admin
from proposals.models import Speech, Talk, Topic from proposals.models import Talk, Topic
admin.site.register(Topic) admin.site.register(Topic)
admin.site.register(Talk) admin.site.register(Talk)
admin.site.register(Speech)

View File

@ -6,5 +6,5 @@ from proposals.models import Talk
__all__ = ['TalkForm'] __all__ = ['TalkForm']
TalkForm = modelform_factory(Talk, fields=['title', 'description', 'topics', 'event'], TalkForm = modelform_factory(Talk, fields=['title', 'description', 'topics', 'event', 'speakers'],
widgets={'topics': CheckboxSelectMultiple()}) widgets={'topics': CheckboxSelectMultiple()})

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-15 09:49 # Generated by Django 1.9.7 on 2016-06-29 22:03
from __future__ import unicode_literals from __future__ import unicode_literals
import autoslug.fields import autoslug.fields
@ -8,6 +8,7 @@ import django.contrib.sites.managers
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import django.db.models.manager import django.db.models.manager
import sortedm2m.fields
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -15,34 +16,29 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('accounts', '0001_initial'),
('sites', '0002_alter_domain_unique'), ('sites', '0002_alter_domain_unique'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ operations = [
migrations.CreateModel(
name='Speech',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('order', models.IntegerField(choices=[(1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5'), (6, '6'), (7, '7')], default=1)),
('speaker', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['talk', 'order'],
},
),
migrations.CreateModel( migrations.CreateModel(
name='Talk', name='Talk',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('title', models.CharField(max_length=128, verbose_name='Title')), ('title', models.CharField(max_length=128, verbose_name='Title')),
('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='title', unique=True)), ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='title', unique=True)),
('description', models.TextField(blank=True, verbose_name='Description')), ('description', models.TextField(blank=True, verbose_name='Description')),
('event', models.IntegerField(choices=[(1, 'conference'), (2, 'workshop'), (3, 'stand'), (4, 'other')], default=1)), ('event', models.IntegerField(choices=[(1, 'conference short'), (2, 'conference long'), (3, 'workshop'), (4, 'stand'), (5, 'other')], default=1)),
('proposer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)), ('proposer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.Site')), ('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
('speakers', models.ManyToManyField(through='proposals.Speech', to=settings.AUTH_USER_MODEL)), ('speakers', sortedm2m.fields.SortedManyToManyField(help_text=None, to=settings.AUTH_USER_MODEL)),
], ],
options={
'abstract': False,
},
managers=[ managers=[
('objects', django.db.models.manager.Manager()), ('objects', django.db.models.manager.Manager()),
('on_site', django.contrib.sites.managers.CurrentSiteManager()), ('on_site', django.contrib.sites.managers.CurrentSiteManager()),
@ -52,22 +48,19 @@ class Migration(migrations.Migration):
name='Topic', name='Topic',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')),
('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True)), ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True)),
('reviewers', models.ManyToManyField(blank=True, to='accounts.Participation')),
], ],
options={
'abstract': False,
},
), ),
migrations.AddField( migrations.AddField(
model_name='talk', model_name='talk',
name='topics', name='topics',
field=models.ManyToManyField(blank=True, to='proposals.Topic'), field=models.ManyToManyField(blank=True, to='proposals.Topic'),
), ),
migrations.AddField(
model_name='speech',
name='talk',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='proposals.Talk'),
),
migrations.AlterUniqueTogether(
name='speech',
unique_together=set([('order', 'talk'), ('speaker', 'talk')]),
),
] ]

View File

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-19 20:26
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0004_remove_participation_review_topics'),
('proposals', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='topic',
name='reviewers',
field=models.ManyToManyField(blank=True, to='accounts.Participation'),
),
]

View File

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-25 10:37
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('proposals', '0002_topic_reviewers'),
]
operations = [
migrations.AlterField(
model_name='talk',
name='event',
field=models.IntegerField(choices=[(1, 'conference short'), (2, 'conference long'), (3, 'workshop'), (4, 'stand'), (5, 'other')], default=1),
),
]

View File

@ -1,53 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-25 11:37
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('proposals', '0003_auto_20160625_1037'),
]
operations = [
migrations.AddField(
model_name='speech',
name='created',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 6, 25, 11, 37, 17, 777177, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='speech',
name='updated',
field=models.DateTimeField(auto_now=True, default=datetime.datetime(2016, 6, 25, 11, 37, 19, 212622, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='talk',
name='created',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 6, 25, 11, 37, 20, 576319, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='talk',
name='updated',
field=models.DateTimeField(auto_now=True, default=datetime.datetime(2016, 6, 25, 11, 37, 21, 782675, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='topic',
name='created',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 6, 25, 11, 37, 23, 418591, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='topic',
name='updated',
field=models.DateTimeField(auto_now=True, default=datetime.datetime(2016, 6, 25, 11, 37, 24, 722598, tzinfo=utc)),
preserve_default=False,
),
]

View File

@ -7,11 +7,12 @@ from django.core.urlresolvers import reverse
from django.db import models from django.db import models
from autoslug import AutoSlugField from autoslug import AutoSlugField
from sortedm2m.fields import SortedManyToManyField
from accounts.models import Participation from accounts.models import Participation
from ponyconf.utils import PonyConfModel, enum_to_choices from ponyconf.utils import PonyConfModel, enum_to_choices
__all__ = ['Topic', 'Talk', 'Speech'] __all__ = ['Topic', 'Talk']
class Topic(PonyConfModel): class Topic(PonyConfModel):
@ -35,7 +36,7 @@ class Talk(PonyConfModel):
site = models.ForeignKey(Site, on_delete=models.CASCADE) site = models.ForeignKey(Site, on_delete=models.CASCADE)
proposer = models.ForeignKey(User, related_name='+') proposer = models.ForeignKey(User, related_name='+')
speakers = models.ManyToManyField(User, through='Speech') speakers = SortedManyToManyField(User)
title = models.CharField(max_length=128, verbose_name='Title') title = models.CharField(max_length=128, verbose_name='Title')
slug = AutoSlugField(populate_from='title', unique=True) slug = AutoSlugField(populate_from='title', unique=True)
description = models.TextField(blank=True, verbose_name='Description') description = models.TextField(blank=True, verbose_name='Description')
@ -63,28 +64,3 @@ class Talk(PonyConfModel):
except Participation.DoesNotExists: except Participation.DoesNotExists:
return False return False
return participation.orga or self.topics.filter(reviewers=participation).exists() return participation.orga or self.topics.filter(reviewers=participation).exists()
class Speech(PonyConfModel):
SPEAKER_NO = tuple((i, str(i)) for i in range(1, 8))
speaker = models.ForeignKey(User, on_delete=models.CASCADE)
talk = models.ForeignKey(Talk, on_delete=models.CASCADE)
order = models.IntegerField(choices=SPEAKER_NO, default=1)
class Meta:
ordering = ['talk', 'order']
unique_together = (
('speaker', 'talk'),
('order', 'talk'),
)
def __str__(self):
return '%s speaking at %s in position %d' % (self.speaker, self.talk, self.order)
def get_absolute_url(self):
return self.talk.get_absolute_url()
def username(self):
return self.speaker.username

View File

@ -1,6 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load bootstrap3 %} {% load bootstrap3 staticfiles %}
{% block talktab %} class="active"{% endblock %} {% block talktab %} class="active"{% endblock %}
@ -11,3 +11,10 @@
{% include "_form.html" %} {% include "_form.html" %}
{% endblock %} {% endblock %}
{% block css %}<link href="{% static 'sortedm2m/widget.css' %}" rel="stylesheet">{% endblock %}
{% block js_end %}
<script src="{% static 'sortedm2m/jquery-ui.js' %}"></script>
<script src="{% static 'sortedm2m/widget.js' %}"></script>
{% endblock js_end %}

View File

@ -5,7 +5,7 @@ from django.test import TestCase
from accounts.models import Participation from accounts.models import Participation
from .models import Speech, Talk, Topic from .models import Talk, Topic
class ProposalsTests(TestCase): class ProposalsTests(TestCase):
@ -19,19 +19,20 @@ class ProposalsTests(TestCase):
def test_everything(self): def test_everything(self):
# talk-edit # talk-edit
self.client.login(username='a', password='a') self.client.login(username='a', password='a')
self.client.post(reverse('add-talk'), {'title': 'super talk', 'description': 'super', 'event': 1, 'topics': 1}) self.client.post(reverse('add-talk'), {'title': 'super talk', 'description': 'super', 'event': 1, 'topics': 1,
self.assertEqual(str(Talk.on_site.first()), 'super talk') 'speakers': 1})
self.assertEqual(Talk.on_site.first().description, 'super') talk = Talk.on_site.first()
self.assertEqual(str(talk), 'super talk')
self.assertEqual(talk.description, 'super')
self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}), self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),
{'title': 'mega talk', 'description': 'mega', 'event': 1}) {'title': 'mega talk', 'description': 'mega', 'event': 1, 'speakers': 1})
self.assertEqual(str(Talk.on_site.first()), 'super talk') # title is read only there self.assertEqual(str(talk), 'super talk') # title is read only there
self.assertEqual(Talk.on_site.first().description, 'mega') talk = Talk.on_site.first()
self.assertEqual(talk.description, 'mega')
# Status Code # Status Code
self.client.login(username='a', password='a')
for view in ['home', 'list-talks', 'add-talk', 'list-topics', 'list-speakers']: for view in ['home', 'list-talks', 'add-talk', 'list-topics', 'list-speakers']:
self.assertEqual(self.client.get(reverse(view)).status_code, 302 if view == 'list-speakers' else 200) self.assertEqual(self.client.get(reverse(view)).status_code, 302 if view == 'list-speakers' else 200)
talk = Talk.on_site.first()
self.assertEqual(self.client.get(reverse('edit-talk', kwargs={'talk': talk.slug})).status_code, 200) self.assertEqual(self.client.get(reverse('edit-talk', kwargs={'talk': talk.slug})).status_code, 200)
self.assertEqual(self.client.get(reverse('show-talk', kwargs={'slug': talk.slug})).status_code, 200) self.assertEqual(self.client.get(reverse('show-talk', kwargs={'slug': talk.slug})).status_code, 200)
self.assertEqual(self.client.get(reverse('list-talks-by-speaker', kwargs={'speaker': 'a'})).status_code, 200) self.assertEqual(self.client.get(reverse('list-talks-by-speaker', kwargs={'speaker': 'a'})).status_code, 200)
@ -43,14 +44,16 @@ class ProposalsTests(TestCase):
self.assertEqual(self.client.get(reverse('list-talks')).status_code, 200) self.assertEqual(self.client.get(reverse('list-talks')).status_code, 200)
# Models str & get_asbolute_url # Models str & get_asbolute_url
for model in [Talk, Topic, Speech]: for model in [Talk, Topic]:
item = model.objects.first() item = model.objects.first()
self.assertEqual(self.client.get(item.get_absolute_url()).status_code, 200) self.assertEqual(self.client.get(item.get_absolute_url()).status_code, 200)
self.assertTrue(str(item)) self.assertTrue(str(item))
self.assertEqual(Speech.objects.first().username(), 'a')
# Talkis_editable_by # Talk.is_editable_by
a, b, c = User.objects.all() a, b, c = User.objects.all()
self.assertTrue(talk.is_editable_by(c)) self.assertTrue(talk.is_editable_by(c))
Speech.objects.create(talk=talk, speaker=b, order=2) self.assertFalse(talk.is_editable_by(b))
self.client.login(username='a', password='a')
self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),
{'title': 'mega talk', 'description': 'mega', 'event': 1, 'speakers': "2,1"})
self.assertTrue(talk.is_editable_by(b)) self.assertTrue(talk.is_editable_by(b))

View File

@ -9,9 +9,9 @@ from django.views.generic import CreateView, DetailView, ListView
from accounts.mixins import StaffRequiredMixin from accounts.mixins import StaffRequiredMixin
from accounts.models import Participation from accounts.models import Participation
from proposals.forms import TalkForm
from proposals.models import Speech, Talk, Topic
from .forms import TalkForm
from .models import Talk, Topic
from .signals import new_talk from .signals import new_talk
@ -59,17 +59,16 @@ def talk_edit(request, talk=None):
if talk: if talk:
form.fields['title'].disabled = True form.fields['title'].disabled = True
form.fields['topics'].disabled = True form.fields['topics'].disabled = True
else:
form.fields['speakers'].initial = [request.user]
if request.method == 'POST' and form.is_valid(): if request.method == 'POST' and form.is_valid():
if hasattr(talk, 'id'): if hasattr(talk, 'id'):
talk = form.save() talk = form.save()
messages.success(request, 'Talk modified successfully!') messages.success(request, 'Talk modified successfully!')
else: else:
talk = form.save(commit=False) form.instance.site = get_current_site(request)
talk.site = get_current_site(request) form.instance.proposer = request.user
talk.proposer = request.user talk = form.save()
talk.save()
form.save_m2m()
Speech.objects.create(speaker=request.user, talk=talk)
new_talk.send(talk.__class__, instance=talk) new_talk.send(talk.__class__, instance=talk)
messages.success(request, 'Talk proposed successfully!') messages.success(request, 'Talk proposed successfully!')
return redirect(talk.get_absolute_url()) return redirect(talk.get_absolute_url())
@ -95,7 +94,7 @@ class TopicCreate(StaffRequiredMixin, CreateView):
class SpeakerList(StaffRequiredMixin, ListView): class SpeakerList(StaffRequiredMixin, ListView):
queryset = User.objects.filter(speech__talk__in=Talk.on_site.all()).distinct() queryset = User.objects.filter(talk__in=Talk.on_site.all()).distinct()
template_name = 'proposals/speaker_list.html' template_name = 'proposals/speaker_list.html'

View File

@ -1,7 +1,8 @@
django<1.10 django<1.10
django-bower
django-bootstrap3
django-autoslug django-autoslug
django-bootstrap3
django-bower
django-registration-redux django-registration-redux
django-sortedm2m
-e git://github.com/Nim65s/django-YummyEmailOrUsernameInsensitiveAuth.git#egg=django-yeouia -e git://github.com/Nim65s/django-YummyEmailOrUsernameInsensitiveAuth.git#egg=django-yeouia