Revision 64438aee
Added by Serghei Mihai almost 10 years ago
uauth/organization/forms.py | ||
---|---|---|
27 | 27 |
class LocalAccountCreateForm(LocalAccountForm): |
28 | 28 |
accounts_number = forms.IntegerField(_('Number of accounts to create'), required=False) |
29 | 29 |
accounts_number_start = forms.IntegerField(_('First number of multiple accounts'), required=False) |
30 |
|
|
31 |
|
|
32 |
class UsersImportForm(forms.Form): |
|
33 |
users_file = forms.FileField(_('Users file')) |
uauth/organization/templates/organization/import_users.html | ||
---|---|---|
1 |
{% extends 'uauth/base.html' %} |
|
2 |
{% load i18n %} |
|
3 |
|
|
4 |
{% block content %} |
|
5 |
<form method="post" action="{% url "import-users" organization.slug %}" enctype="multipart/form-data"> |
|
6 |
{% csrf_token %} |
|
7 |
{{ form.as_p }} |
|
8 |
<h3>{% trans "Expected file format" %}: CSV</h3> |
|
9 |
<ul> |
|
10 |
<li>{% trans "5 columns: login, first name, last name, expiration date, password" %}</li> |
|
11 |
<li>{% trans "date format: YYYY-MM-DD" %}</li> |
|
12 |
<li>{% trans "if empty password, it will be generated" %}</li> |
|
13 |
<li>{% trans "if user exists, it will be updated" %}</li> |
|
14 |
<li>{% trans "separator: comma" %}</li> |
|
15 |
<li>{% trans "encoding: utf-8" %}</li> |
|
16 |
<li>{% trans "first line is ignored" %}</li> |
|
17 |
</ul> |
|
18 |
<p>Example: |
|
19 |
<div class="example"> |
|
20 |
"login", "first name", "last name", "expiration", "password"<br /> |
|
21 |
"foo", "Foo", "User", "2015-12-31", "secret" <br /> |
|
22 |
"bar", "User", "Bar", "2015-04-30", ""<br /> |
|
23 |
"test", "", "", "", ""<br /> |
|
24 |
</div> |
|
25 |
</p> |
|
26 |
<p><button name="upload">{% trans "Import" %}</button> |
|
27 |
</form> |
|
28 |
{% endblock %} |
uauth/organization/templates/organization/users.html | ||
---|---|---|
7 | 7 |
|
8 | 8 |
{% block appbar %} |
9 | 9 |
<h2>{% trans "Local users" %}</h2> |
10 |
<a href="{% url "import-users" organization.slug %}" rel="popup">{% trans "Import users" %}</a> |
|
10 | 11 |
<a href="{% url "create-users" organization.slug %}" rel="popup">{% trans "Create users" %}</a> |
11 | 12 |
{% endblock %} |
12 | 13 |
|
uauth/organization/urls.py | ||
---|---|---|
6 | 6 |
url(r'^$', manage, name='manage'), |
7 | 7 |
url(r'^users/?$', users, name='manage-users'), |
8 | 8 |
url(r'^users/create$', create_users, name='create-users'), |
9 |
url(r'^users/import$', import_users, name='import-users'), |
|
9 | 10 |
url(r'^users/(?P<pk>[\w]+)/$', view_user, name='view-user'), |
10 | 11 |
url(r'^users/(?P<pk>[\w]+)/edit$', edit_user, name='edit-user'), |
11 | 12 |
) |
uauth/organization/utils.py | ||
---|---|---|
18 | 18 |
return user |
19 | 19 |
except: |
20 | 20 |
return False |
21 |
|
|
22 |
def create_or_update_users(data): |
|
23 |
created = 0 |
|
24 |
updated = 0 |
|
25 |
for user in data: |
|
26 |
try: |
|
27 |
account = LocalAccount.objects.get(username=user['username']) |
|
28 |
if not user['password']: |
|
29 |
del user['password'] |
|
30 |
account.__dict__.update(user) |
|
31 |
account.save() |
|
32 |
updated += 1 |
|
33 |
except LocalAccount.DoesNotExist: |
|
34 |
if create_user(user): |
|
35 |
created += 1 |
|
36 |
return created, updated |
uauth/organization/views.py | ||
---|---|---|
1 |
import csv |
|
2 |
import datetime |
|
3 |
|
|
1 | 4 |
from django.utils.translation import ugettext as _ |
2 | 5 |
from django.core.urlresolvers import reverse_lazy |
3 |
from django.http import HttpResponseRedirect
|
|
6 |
from django.shortcuts import render, redirect
|
|
4 | 7 |
|
5 | 8 |
from django.views.generic.base import TemplateView |
6 | 9 |
from django.views.generic.list import ListView |
7 | 10 |
from django.views.generic.edit import FormView, UpdateView |
8 |
from django.views.generic import DetailView |
|
11 |
from django.views.generic import DetailView, View
|
|
9 | 12 |
from django.contrib import messages |
10 | 13 |
|
11 | 14 |
from django_tables2 import RequestConfig |
12 | 15 |
|
13 |
from .utils import create_user |
|
16 |
from .utils import create_user, create_or_update_users
|
|
14 | 17 |
from .models import LocalAccount, Organization |
15 |
from .forms import LocalAccountCreateForm, LocalAccountForm |
|
18 |
from .forms import LocalAccountCreateForm, LocalAccountForm, UsersImportForm
|
|
16 | 19 |
from .tables import AccountTable |
17 | 20 |
|
18 | 21 |
|
... | ... | |
96 | 99 |
if 'delete' in self.request.POST: |
97 | 100 |
self.object.delete() |
98 | 101 |
messages.info(self.request, _('Account "%s" successfully deleted' % username)) |
99 |
return HttpResponseRedirect(self.get_success_url())
|
|
102 |
return redirect(self.get_success_url())
|
|
100 | 103 |
else: |
101 | 104 |
messages.info(self.request, _('Account "%s" successfully updated' % username)) |
102 | 105 |
return super(UserEditView, self).form_valid(form) |
103 | 106 |
|
104 | 107 |
edit_user = UserEditView.as_view() |
108 |
|
|
109 |
|
|
110 |
class ImportUsersView(OrganizationMixin, TemplateView): |
|
111 |
form_class = UsersImportForm |
|
112 |
template_name = 'organization/import_users.html' |
|
113 |
|
|
114 |
def get_context_data(self, **kwargs): |
|
115 |
ctx = super(ImportUsersView, self).get_context_data(**kwargs) |
|
116 |
ctx['form'] = self.form_class() |
|
117 |
return ctx |
|
118 |
|
|
119 |
def post(self, request, *args, **kwargs): |
|
120 |
form = self.form_class(request.POST, request.FILES) |
|
121 |
context = self.get_context_data(**kwargs) |
|
122 |
context['form'] = form |
|
123 |
if form.is_valid(): |
|
124 |
data = form.cleaned_data['users_file'] |
|
125 |
dialect = csv.Sniffer().sniff(data.read(1024)) |
|
126 |
data.seek(0) |
|
127 |
reader = csv.reader(data, dialect) |
|
128 |
reader.next() |
|
129 |
users = [] |
|
130 |
for row in reader: |
|
131 |
try: |
|
132 |
user = {'username': row[0].strip(), |
|
133 |
'first_name': row[1].strip(), |
|
134 |
'last_name': row[2].strip(), |
|
135 |
'password': row[4].strip(), |
|
136 |
'organization': context['organization'] |
|
137 |
} |
|
138 |
except IndexError: |
|
139 |
# ignore wrong lines |
|
140 |
continue |
|
141 |
try: |
|
142 |
user['expiration_date'] = datetime.datetime.strptime(row[3], '%Y-%m-%d') |
|
143 |
except ValueError: |
|
144 |
pass |
|
145 |
users.append(user) |
|
146 |
created, updated = create_or_update_users(users) |
|
147 |
if created: |
|
148 |
messages.info(request, _('%s accounts added' % created)) |
|
149 |
if updated: |
|
150 |
messages.info(request, _('%s accounts updated' % updated)) |
|
151 |
return redirect(self.get_success_url()) |
|
152 |
else: |
|
153 |
return self.render_to_response(context) |
|
154 |
|
|
155 |
import_users = ImportUsersView.as_view() |
uauth/static/css/style.css | ||
---|---|---|
61 | 61 |
.icon-delete:before { |
62 | 62 |
content: '\f1f8'; |
63 | 63 |
margin: 0 3px; |
64 |
} |
|
65 |
|
|
66 |
div.example { |
|
67 |
background: #eee; |
|
68 |
border: 1px solid #bbb; |
|
69 |
font-family: Monospace; |
|
64 | 70 |
} |
Also available in: Unified diff
import users view(#7065)