import users view(#7065)
This commit is contained in:
parent
7b4999305a
commit
64438aee02
|
@ -27,3 +27,7 @@ class LocalAccountForm(forms.ModelForm):
|
|||
class LocalAccountCreateForm(LocalAccountForm):
|
||||
accounts_number = forms.IntegerField(_('Number of accounts to create'), required=False)
|
||||
accounts_number_start = forms.IntegerField(_('First number of multiple accounts'), required=False)
|
||||
|
||||
|
||||
class UsersImportForm(forms.Form):
|
||||
users_file = forms.FileField(_('Users file'))
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{% extends 'uauth/base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post" action="{% url "import-users" organization.slug %}" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<h3>{% trans "Expected file format" %}: CSV</h3>
|
||||
<ul>
|
||||
<li>{% trans "5 columns: login, first name, last name, expiration date, password" %}</li>
|
||||
<li>{% trans "date format: YYYY-MM-DD" %}</li>
|
||||
<li>{% trans "if empty password, it will be generated" %}</li>
|
||||
<li>{% trans "if user exists, it will be updated" %}</li>
|
||||
<li>{% trans "separator: comma" %}</li>
|
||||
<li>{% trans "encoding: utf-8" %}</li>
|
||||
<li>{% trans "first line is ignored" %}</li>
|
||||
</ul>
|
||||
<p>Example:
|
||||
<div class="example">
|
||||
"login", "first name", "last name", "expiration", "password"<br />
|
||||
"foo", "Foo", "User", "2015-12-31", "secret" <br />
|
||||
"bar", "User", "Bar", "2015-04-30", ""<br />
|
||||
"test", "", "", "", ""<br />
|
||||
</div>
|
||||
</p>
|
||||
<p><button name="upload">{% trans "Import" %}</button>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Local users" %}</h2>
|
||||
<a href="{% url "import-users" organization.slug %}" rel="popup">{% trans "Import users" %}</a>
|
||||
<a href="{% url "create-users" organization.slug %}" rel="popup">{% trans "Create users" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ urlpatterns = patterns('',
|
|||
url(r'^$', manage, name='manage'),
|
||||
url(r'^users/?$', users, name='manage-users'),
|
||||
url(r'^users/create$', create_users, name='create-users'),
|
||||
url(r'^users/import$', import_users, name='import-users'),
|
||||
url(r'^users/(?P<pk>[\w]+)/$', view_user, name='view-user'),
|
||||
url(r'^users/(?P<pk>[\w]+)/edit$', edit_user, name='edit-user'),
|
||||
)
|
||||
|
|
|
@ -18,3 +18,19 @@ def create_user(data):
|
|||
return user
|
||||
except:
|
||||
return False
|
||||
|
||||
def create_or_update_users(data):
|
||||
created = 0
|
||||
updated = 0
|
||||
for user in data:
|
||||
try:
|
||||
account = LocalAccount.objects.get(username=user['username'])
|
||||
if not user['password']:
|
||||
del user['password']
|
||||
account.__dict__.update(user)
|
||||
account.save()
|
||||
updated += 1
|
||||
except LocalAccount.DoesNotExist:
|
||||
if create_user(user):
|
||||
created += 1
|
||||
return created, updated
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
import csv
|
||||
import datetime
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render, redirect
|
||||
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic.list import ListView
|
||||
from django.views.generic.edit import FormView, UpdateView
|
||||
from django.views.generic import DetailView
|
||||
from django.views.generic import DetailView, View
|
||||
from django.contrib import messages
|
||||
|
||||
from django_tables2 import RequestConfig
|
||||
|
||||
from .utils import create_user
|
||||
from .utils import create_user, create_or_update_users
|
||||
from .models import LocalAccount, Organization
|
||||
from .forms import LocalAccountCreateForm, LocalAccountForm
|
||||
from .forms import LocalAccountCreateForm, LocalAccountForm, UsersImportForm
|
||||
from .tables import AccountTable
|
||||
|
||||
|
||||
|
@ -96,9 +99,57 @@ class UserEditView(OrganizationMixin, UpdateView):
|
|||
if 'delete' in self.request.POST:
|
||||
self.object.delete()
|
||||
messages.info(self.request, _('Account "%s" successfully deleted' % username))
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
return redirect(self.get_success_url())
|
||||
else:
|
||||
messages.info(self.request, _('Account "%s" successfully updated' % username))
|
||||
return super(UserEditView, self).form_valid(form)
|
||||
|
||||
edit_user = UserEditView.as_view()
|
||||
|
||||
|
||||
class ImportUsersView(OrganizationMixin, TemplateView):
|
||||
form_class = UsersImportForm
|
||||
template_name = 'organization/import_users.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(ImportUsersView, self).get_context_data(**kwargs)
|
||||
ctx['form'] = self.form_class()
|
||||
return ctx
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.form_class(request.POST, request.FILES)
|
||||
context = self.get_context_data(**kwargs)
|
||||
context['form'] = form
|
||||
if form.is_valid():
|
||||
data = form.cleaned_data['users_file']
|
||||
dialect = csv.Sniffer().sniff(data.read(1024))
|
||||
data.seek(0)
|
||||
reader = csv.reader(data, dialect)
|
||||
reader.next()
|
||||
users = []
|
||||
for row in reader:
|
||||
try:
|
||||
user = {'username': row[0].strip(),
|
||||
'first_name': row[1].strip(),
|
||||
'last_name': row[2].strip(),
|
||||
'password': row[4].strip(),
|
||||
'organization': context['organization']
|
||||
}
|
||||
except IndexError:
|
||||
# ignore wrong lines
|
||||
continue
|
||||
try:
|
||||
user['expiration_date'] = datetime.datetime.strptime(row[3], '%Y-%m-%d')
|
||||
except ValueError:
|
||||
pass
|
||||
users.append(user)
|
||||
created, updated = create_or_update_users(users)
|
||||
if created:
|
||||
messages.info(request, _('%s accounts added' % created))
|
||||
if updated:
|
||||
messages.info(request, _('%s accounts updated' % updated))
|
||||
return redirect(self.get_success_url())
|
||||
else:
|
||||
return self.render_to_response(context)
|
||||
|
||||
import_users = ImportUsersView.as_view()
|
||||
|
|
|
@ -61,4 +61,10 @@ ul.login li, #guest-login ul li, #voucher-login ul li, .loginbox li {
|
|||
.icon-delete:before {
|
||||
content: '\f1f8';
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
div.example {
|
||||
background: #eee;
|
||||
border: 1px solid #bbb;
|
||||
font-family: Monospace;
|
||||
}
|
Reference in New Issue