Merge pull request #1175 from normanjaeckel/MultipleParticipantsForm

Added form field for multiple creation of new participants. Fixed #178.
This commit is contained in:
Norman Jäckel 2014-01-11 15:26:36 -08:00
commit 3fe9169786
7 changed files with 82 additions and 2 deletions

View File

@ -10,6 +10,7 @@ Version 1.6 (unreleased)
Participants: Participants:
- Disabled widgets by default. - Disabled widgets by default.
- Added form field for multiple creation of new participants.
Files: Files:
- Enabled update and delete view for uploader refering to his own files. - Enabled update and delete view for uploader refering to his own files.
Other: Other:

View File

@ -36,6 +36,13 @@ class UserCreateForm(CssClassMixin, forms.ModelForm):
return cleaned_data return cleaned_data
class UserMultipleCreateForm(forms.Form):
participants_block = forms.CharField(
widget=forms.Textarea,
label=ugettext_lazy('Participants'),
help_text=ugettext_lazy('Use one line per participant for its name (first name and last name).'))
class UserUpdateForm(UserCreateForm): class UserUpdateForm(UserCreateForm):
""" """
Form to update an user. It raises a validation error, if a non-superuser Form to update an user. It raises a validation error, if a non-superuser

View File

@ -21,6 +21,7 @@
<small class="pull-right"> <small class="pull-right">
{% if perms.participant.can_manage_participant %} {% if perms.participant.can_manage_participant %}
<a href="{% url 'user_new' %}" class="btn btn-mini btn-primary" rel="tooltip" data-original-title="{% trans 'New participant' %}"><i class="icon-plus icon-white"></i> {% trans "New" %}</a> <a href="{% url 'user_new' %}" class="btn btn-mini btn-primary" rel="tooltip" data-original-title="{% trans 'New participant' %}"><i class="icon-plus icon-white"></i> {% trans "New" %}</a>
<a href="{% url 'user_new_multiple' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'New multiple participants' %}"><i class="icon-plus"></i> {% trans 'New multiple' %}</a>
<a href="{% url 'user_group_overview' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'All groups' %}"><i class="icon-group"></i> {% trans "Groups" %}</a> <a href="{% url 'user_group_overview' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'All groups' %}"><i class="icon-group"></i> {% trans "Groups" %}</a>
<a href="{% url 'user_import' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Import participants' %}"><i class="icon-import"></i> {% trans 'Import' %}</a> <a href="{% url 'user_import' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Import participants' %}"><i class="icon-import"></i> {% trans 'Import' %}</a>
{% endif %} {% endif %}

View File

@ -0,0 +1,28 @@
{% extends "base.html" %}
{% load i18n %}
{% block title %}
{% trans 'New multiple participants' %} {{ block.super }}
{% endblock %}
{% block content %}
<h1>
{% trans 'New multiple participants' %}
<small class="pull-right">
<a href="{% url 'user_overview' %}" class="btn btn-mini">
<i class="icon-chevron-left"></i> {% trans 'Back to overview' %}
</a>
</small>
</h1>
<form action="" method="post">{% csrf_token %}
{% include 'form.html' %}
<p>
{% include 'formbuttons_save.html' %}
<a href="{% url 'user_overview' %}" class="btn">
{% trans 'Cancel' %}
</a>
</p>
<small>* {% trans 'required' %}</small>
</form>
{% endblock %}

View File

@ -15,6 +15,10 @@ urlpatterns = patterns(
views.UserCreateView.as_view(), views.UserCreateView.as_view(),
name='user_new'), name='user_new'),
url(r'^new_multiple/$',
views.UserMultipleCreateView.as_view(),
name='user_new_multiple'),
url(r'^(?P<pk>\d+)/$', url(r'^(?P<pk>\d+)/$',
views.UserDetailView.as_view(), views.UserDetailView.as_view(),
name='user_view'), name='user_view'),

View File

@ -3,6 +3,7 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.hashers import make_password
from django.contrib.auth.views import login as django_login from django.contrib.auth.views import login as django_login
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.shortcuts import redirect from django.shortcuts import redirect
@ -18,8 +19,8 @@ from openslides.utils.views import (CreateView, DeleteView, DetailView,
RedirectView, SingleObjectMixin, UpdateView) RedirectView, SingleObjectMixin, UpdateView)
from .api import gen_password, gen_username, import_users from .api import gen_password, gen_username, import_users
from .forms import (GroupForm, UserCreateForm, UserImportForm, UsersettingsForm, from .forms import (GroupForm, UserCreateForm, UserMultipleCreateForm, UserImportForm,
UserUpdateForm) UsersettingsForm, UserUpdateForm)
from .models import get_protected_perm, Group, User from .models import get_protected_perm, Group, User
from .pdf import participants_to_pdf, participants_passwords_to_pdf from .pdf import participants_to_pdf, participants_passwords_to_pdf
@ -91,6 +92,33 @@ class UserCreateView(CreateView):
self.object.groups.add(registered) self.object.groups.add(registered)
class UserMultipleCreateView(FormView):
"""
View to create multiple users at once using a big text field.
"""
permission_required = 'participant.can_manage_participant'
template_name = 'participant/user_form_multiple.html'
form_class = UserMultipleCreateForm
success_url_name = 'user_overview'
def form_valid(self, form):
# TODO: Use bulk_create after rework of participant.models.User
for number, line in enumerate(form.cleaned_data['participants_block'].splitlines()):
names_list = line.split()
first_name = ' '.join(names_list[:-1])
last_name = names_list[-1]
username = gen_username(first_name, last_name)
default_password = gen_password()
User.objects.create(
username=username,
first_name=first_name,
last_name=last_name,
default_password=default_password,
password=make_password(default_password, '', 'md5'))
messages.success(self.request, _('%(number)d users successfully created.') % {'number': number + 1})
return super(UserMultipleCreateView, self).form_valid(form)
class UserUpdateView(UpdateView): class UserUpdateView(UpdateView):
""" """
Update an existing participant. Update an existing participant.

View File

@ -28,6 +28,17 @@ class UserViews(TestCase):
response = self.client.post('/participant/new/', {'first_name': 'test_name_ho8hui2niz4nohSupahb'}) response = self.client.post('/participant/new/', {'first_name': 'test_name_ho8hui2niz4nohSupahb'})
self.assertRedirects(response, '/participant/') self.assertRedirects(response, '/participant/')
def test_create_multiple(self):
response = self.client.get('/participant/new_multiple/')
self.assertTemplateUsed(response, 'participant/user_form_multiple.html')
self.assertContains(response, 'New multiple participants')
self.assertEqual(User.objects.count(), 1)
block = ('first_name_ksdjfhkjsdhf75utgeitrten last_name_khonizt958zh8fh\n'
'first_name_1_bmgnf7z8ru first_name_2_kjc98vivt last_name_dfg76kjkjuibv')
response = self.client.post('/participant/new_multiple/',
{'participants_block': block})
self.assertEqual(User.objects.count(), 3)
def test_update(self): def test_update(self):
response = self.client.get('/participant/1/edit/') response = self.client.get('/participant/1/edit/')
self.assertTemplateUsed(response, 'participant/edit.html') self.assertTemplateUsed(response, 'participant/edit.html')