PEP8 cleanups.

This commit is contained in:
Roberto Rosario
2015-08-19 14:50:44 -04:00
parent 683e54fea1
commit 68f3c6eee7
49 changed files with 1078 additions and 216 deletions

View File

@@ -10,7 +10,9 @@ from .permissions import permission_acl_view, permission_acl_edit
def get_kwargs_factory(variable_name): def get_kwargs_factory(variable_name):
def get_kwargs(context): def get_kwargs(context):
content_type = ContentType.objects.get_for_model(context[variable_name]) content_type = ContentType.objects.get_for_model(
context[variable_name]
)
return { return {
'app_label': '"{}"'.format(content_type.app_label), 'app_label': '"{}"'.format(content_type.app_label),
'model': '"{}"'.format(content_type.model), 'model': '"{}"'.format(content_type.model),

View File

@@ -2,7 +2,9 @@ from __future__ import unicode_literals
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from .views import ACLCreateView, ACLDeleteView, ACLListView, ACLPermissionsView from .views import (
ACLCreateView, ACLDeleteView, ACLListView, ACLPermissionsView
)
urlpatterns = patterns( urlpatterns = patterns(
'acls.views', 'acls.views',

View File

@@ -11,6 +11,7 @@ from ..settings import setting_login_method
TEST_ADMIN_EMAIL = 'admin@admin.com' TEST_ADMIN_EMAIL = 'admin@admin.com'
TEST_ADMIN_PASSWORD = 'test_admin_password' TEST_ADMIN_PASSWORD = 'test_admin_password'
TEST_ADMIN_USERNAME = 'test_admin' TEST_ADMIN_USERNAME = 'test_admin'
TEST_EMAIL_AUTHENTICATION_BACKEND = 'authentication.auth.email_auth_backend.EmailAuthBackend'
class UserLoginTestCase(TestCase): class UserLoginTestCase(TestCase):
@@ -43,7 +44,7 @@ class UserLoginTestCase(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_email_login(self): def test_email_login(self):
with self.settings(AUTHENTICATION_BACKENDS=('authentication.auth.email_auth_backend.EmailAuthBackend',)): with self.settings(AUTHENTICATION_BACKENDS=(TEST_EMAIL_AUTHENTICATION_BACKEND,)):
setting_login_method.value = 'email' setting_login_method.value = 'email'
logged_in = self.client.login( logged_in = self.client.login(
@@ -78,7 +79,7 @@ class UserLoginTestCase(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_email_login_via_views(self): def test_email_login_via_views(self):
with self.settings(AUTHENTICATION_BACKENDS=('authentication.auth.email_auth_backend.EmailAuthBackend',)): with self.settings(AUTHENTICATION_BACKENDS=(TEST_EMAIL_AUTHENTICATION_BACKEND,)):
setting_login_method.value = 'email' setting_login_method.value = 'email'
response = self.client.get(reverse('documents:document_list')) response = self.client.get(reverse('documents:document_list'))
self.assertRedirects( self.assertRedirects(

View File

@@ -118,7 +118,9 @@ class APICheckedoutDocumentView(generics.RetrieveDestroyAPIView):
filtered_documents = documents filtered_documents = documents
return DocumentCheckout.objects.filter( return DocumentCheckout.objects.filter(
document__pk__in=filtered_documents.values_list('pk', flat=True) document__pk__in=filtered_documents.values_list(
'pk', flat=True
)
) )
elif self.request.method == 'DELETE': elif self.request.method == 'DELETE':
return DocumentCheckout.objects.all() return DocumentCheckout.objects.all()
@@ -155,7 +157,10 @@ class APICheckedoutDocumentView(generics.RetrieveDestroyAPIView):
) )
except PermissionDenied: except PermissionDenied:
AccessControlList.objects.check_access( AccessControlList.objects.check_access(
permission_document_checkin_override, request.user, document permission_document_checkin_override, request.user,
document
) )
return super(APICheckedoutDocumentView, self).delete(request, *args, **kwargs) return super(
APICheckedoutDocumentView, self
).delete(request, *args, **kwargs)

View File

@@ -10,6 +10,7 @@ def check_if_new_versions_allowed(sender, **kwargs):
if not DocumentCheckout.objects.are_document_new_versions_allowed(kwargs['instance'].document): if not DocumentCheckout.objects.are_document_new_versions_allowed(kwargs['instance'].document):
raise NewDocumentVersionNotAllowed( raise NewDocumentVersionNotAllowed(
_( _(
'New versions not allowed for the checkedout document: %s' % kwargs['instance'].document 'New versions not allowed for the checkedout document: %s'
% kwargs['instance'].document
) )
) )

View File

@@ -15,13 +15,53 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='DocumentCheckout', name='DocumentCheckout',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
('checkout_datetime', models.DateTimeField(auto_now_add=True, verbose_name='Check out date and time')), 'id', models.AutoField(
('expiration_datetime', models.DateTimeField(help_text='Amount of time to hold the document checked out in minutes.', verbose_name='Check out expiration date and time')), verbose_name='ID', serialize=False, auto_created=True,
('user_object_id', models.PositiveIntegerField(null=True, blank=True)), primary_key=True
('block_new_version', models.BooleanField(default=True, help_text='Do not allow new version of this document to be uploaded.', verbose_name='Block new version upload')), )
('document', models.ForeignKey(verbose_name='Document', to='documents.Document', unique=True)), ),
('user_content_type', models.ForeignKey(blank=True, to='contenttypes.ContentType', null=True)), (
'checkout_datetime',
models.DateTimeField(
auto_now_add=True,
verbose_name='Check out date and time'
)
),
(
'expiration_datetime',
models.DateTimeField(
help_text='Amount of time to hold the document '
'checked out in minutes.',
verbose_name='Check out expiration date and time'
)
),
(
'user_object_id',
models.PositiveIntegerField(null=True, blank=True)
),
(
'block_new_version',
models.BooleanField(
default=True,
help_text='Do not allow new version of this document '
'to be uploaded.',
verbose_name='Block new version upload'
)
),
(
'document',
models.ForeignKey(
verbose_name='Document', to='documents.Document',
unique=True
)
),
(
'user_content_type',
models.ForeignKey(
blank=True, to='contenttypes.ContentType', null=True
)
),
], ],
options={ options={
'verbose_name': 'Document checkout', 'verbose_name': 'Document checkout',

View File

@@ -16,7 +16,10 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='documentcheckout', model_name='documentcheckout',
name='user', name='user',
field=models.ForeignKey(verbose_name='User', blank=True, to=settings.AUTH_USER_MODEL, null=True), field=models.ForeignKey(
verbose_name='User', blank=True, to=settings.AUTH_USER_MODEL,
null=True
),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -23,5 +23,7 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.RunPython(move_from_content_type_user_to_foreign_key_field_user), migrations.RunPython(
move_from_content_type_user_to_foreign_key_field_user
),
] ]

View File

@@ -23,7 +23,9 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='documentcheckout', model_name='documentcheckout',
name='user', name='user',
field=models.ForeignKey(verbose_name='User', to=settings.AUTH_USER_MODEL), field=models.ForeignKey(
verbose_name='User', to=settings.AUTH_USER_MODEL
),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -11,7 +11,8 @@ from common.literals import TIME_DELTA_UNIT_CHOICES
class SplitTimeDeltaWidget(forms.widgets.MultiWidget): class SplitTimeDeltaWidget(forms.widgets.MultiWidget):
""" """
A Widget that splits a timedelta input into three <input type="text"> boxes. A Widget that splits a timedelta input into three <input type="text">
boxes.
""" """
def __init__(self, attrs=None): def __init__(self, attrs=None):

View File

@@ -18,8 +18,8 @@ class ModelAttribute(object):
return result return result
except IndexError: except IndexError:
# We were passed a model instance, try again using the model of the # We were passed a model instance, try again using the model of
# instance # the instance
# If we are already in the model class, exit with an error # If we are already in the model class, exit with an error
if model.__class__ == models.base.ModelBase: if model.__class__ == models.base.ModelBase:
@@ -30,16 +30,24 @@ class ModelAttribute(object):
@classmethod @classmethod
def get_choices_for(cls, model, type_names=None): def get_choices_for(cls, model, type_names=None):
return [ return [
(attribute.name, attribute) for attribute in cls.get_for(model, type_names) (
attribute.name, attribute
) for attribute in cls.get_for(model, type_names)
] ]
@classmethod @classmethod
def help_text_for(cls, model, type_names=None): def help_text_for(cls, model, type_names=None):
result = [] result = []
for count, attribute in enumerate(cls.get_for(model, type_names), 1): for count, attribute in enumerate(cls.get_for(model, type_names), 1):
result.append('{}) {}'.format(count, unicode(attribute.get_display(show_name=True)))) result.append(
'{}) {}'.format(
count, unicode(attribute.get_display(show_name=True))
)
)
return ' '.join([ugettext('Available attributes: '), ', '.join(result)]) return ' '.join(
[ugettext('Available attributes: '), ', '.join(result)]
)
def get_display(self, show_name=False): def get_display(self, show_name=False):
if self.description: if self.description:

View File

@@ -101,7 +101,9 @@ class CompressedFile(object):
filename for filename in zfobj.namelist() if not filename.endswith('/') filename for filename in zfobj.namelist() if not filename.endswith('/')
] ]
return ( return (
SimpleUploadedFile(name=filename, content=zfobj.read(filename)) for filename in filenames SimpleUploadedFile(
name=filename, content=zfobj.read(filename)
) for filename in filenames
) )
except zipfile.BadZipfile: except zipfile.BadZipfile:
raise NotACompressedFile raise NotACompressedFile

View File

@@ -54,7 +54,9 @@ class DetailForm(forms.ModelForm):
self.fields[field_name].help_text = '' self.fields[field_name].help_text = ''
for field_name, field in self.fields.items(): for field_name, field in self.fields.items():
self.fields[field_name].widget.attrs.update({'readonly': 'readonly'}) self.fields[field_name].widget.attrs.update(
{'readonly': 'readonly'}
)
class ChoiceForm(forms.Form): class ChoiceForm(forms.Form):

View File

@@ -4,11 +4,9 @@ from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured from django.http import HttpResponseRedirect
from django.http import Http404, HttpResponseRedirect
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic import FormView, TemplateView from django.views.generic import FormView, TemplateView
from django.views.generic.detail import SingleObjectMixin
from django.views.generic.edit import CreateView, DeleteView, UpdateView from django.views.generic.edit import CreateView, DeleteView, UpdateView
from django.views.generic.list import ListView from django.views.generic.list import ListView
@@ -110,7 +108,9 @@ class AssignRemoveView(ExtraContextMixin, ViewPermissionCheckMixin, ObjectPermis
label = dict(flat_list)[selection] label = dict(flat_list)[selection]
if self.decode_content_type: if self.decode_content_type:
model, pk = selection.split(',') model, pk = selection.split(',')
selection_obj = ContentType.objects.get(model=model).get_object_for_this_type(pk=pk) selection_obj = ContentType.objects.get(
model=model
).get_object_for_this_type(pk=pk)
else: else:
selection_obj = selection selection_obj = selection
@@ -202,7 +202,9 @@ class MultiFormView(FormView):
def get_forms(self, form_classes): def get_forms(self, form_classes):
return dict( return dict(
[ [
(key, self._create_form(key, klass)) for key, klass in form_classes.items() (
key, self._create_form(key, klass)
) for key, klass in form_classes.items()
] ]
) )
@@ -270,7 +272,9 @@ class SingleObjectCreateView(ViewPermissionCheckMixin, ExtraContextMixin, Redire
try: try:
messages.success( messages.success(
self.request, self.request,
_('%s created successfully.') % self.extra_context['object_name'].capitalize() _(
'%s created successfully.'
) % self.extra_context['object_name'].capitalize()
) )
except KeyError: except KeyError:
messages.success( messages.success(
@@ -294,7 +298,8 @@ class SingleObjectDeleteView(ViewPermissionCheckMixin, ObjectPermissionCheckMixi
except Exception as exception: except Exception as exception:
try: try:
messages.error( messages.error(
self.request, _('Error deleting %s.') % self.extra_context['object_name'] self.request,
_('Error deleting %s.') % self.extra_context['object_name']
) )
except KeyError: except KeyError:
messages.error( messages.error(
@@ -305,7 +310,10 @@ class SingleObjectDeleteView(ViewPermissionCheckMixin, ObjectPermissionCheckMixi
else: else:
try: try:
messages.success( messages.success(
self.request, _('%s deleted successfully.') % self.extra_context['object_name'].capitalize() self.request,
_(
'%s deleted successfully.'
) % self.extra_context['object_name'].capitalize()
) )
except KeyError: except KeyError:
messages.success( messages.success(
@@ -325,7 +333,10 @@ class SingleObjectEditView(ViewPermissionCheckMixin, ObjectPermissionCheckMixin,
try: try:
messages.error( messages.error(
self.request, _('Error saving %s details.') % self.extra_context['object_name'] self.request,
_(
'Error saving %s details.'
) % self.extra_context['object_name']
) )
except KeyError: except KeyError:
messages.error( messages.error(
@@ -339,7 +350,10 @@ class SingleObjectEditView(ViewPermissionCheckMixin, ObjectPermissionCheckMixin,
try: try:
messages.success( messages.success(
self.request, _('%s details saved successfully.') % self.extra_context['object_name'].capitalize() self.request,
_(
'%s details saved successfully.'
) % self.extra_context['object_name'].capitalize()
) )
except KeyError: except KeyError:
messages.success( messages.success(
@@ -354,4 +368,3 @@ class SingleObjectListView(PaginationMixin, ViewPermissionCheckMixin, ObjectList
def get_paginate_by(self, queryset): def get_paginate_by(self, queryset):
return setting_paginate_by.value return setting_paginate_by.value

View File

@@ -8,5 +8,7 @@ class AjaxRedirect(object):
def process_response(self, request, response): def process_response(self, request, response):
if request.is_ajax(): if request.is_ajax():
if type(response) == HttpResponseRedirect: if type(response) == HttpResponseRedirect:
response.status_code = getattr(settings, 'AJAX_REDIRECT_CODE', 302) response.status_code = getattr(
settings, 'AJAX_REDIRECT_CODE', 302
)
return response return response

File diff suppressed because one or more lines are too long

View File

@@ -49,7 +49,8 @@ class ObjectListPermissionFilterMixin(object):
self.request.user, (self.object_permission,) self.request.user, (self.object_permission,)
) )
except PermissionDenied: except PermissionDenied:
# No global permission, filter ther queryset per object + permission # No global permission, filter ther queryset per object +
# permission
return AccessControlList.objects.filter_by_access( return AccessControlList.objects.filter_by_access(
self.object_permission, self.request.user, queryset self.object_permission, self.request.user, queryset
) )
@@ -79,7 +80,9 @@ class ObjectPermissionCheckMixin(object):
self.get_permission_object() self.get_permission_object()
) )
return super(ObjectPermissionCheckMixin, self).dispatch(request, *args, **kwargs) return super(
ObjectPermissionCheckMixin, self
).dispatch(request, *args, **kwargs)
class RedirectionMixin(object): class RedirectionMixin(object):
@@ -111,7 +114,9 @@ class RedirectionMixin(object):
) )
) )
return super(RedirectionMixin, self).dispatch(request, *args, **kwargs) return super(
RedirectionMixin, self
).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(RedirectionMixin, self).get_context_data(**kwargs) context = super(RedirectionMixin, self).get_context_data(**kwargs)
@@ -137,4 +142,6 @@ class ViewPermissionCheckMixin(object):
self.request.user, (self.view_permission,) self.request.user, (self.view_permission,)
) )
return super(ViewPermissionCheckMixin, self).dispatch(request, *args, **kwargs) return super(
ViewPermissionCheckMixin, self
).dispatch(request, *args, **kwargs)

View File

@@ -9,7 +9,11 @@ from smart_settings import Namespace
namespace = Namespace(name='common', label=_('Common')) namespace = Namespace(name='common', label=_('Common'))
setting_temporary_directory = namespace.add_setting( setting_temporary_directory = namespace.add_setting(
global_name='COMMON_TEMPORARY_DIRECTORY', default=tempfile.gettempdir(), global_name='COMMON_TEMPORARY_DIRECTORY', default=tempfile.gettempdir(),
help_text=_('Temporary directory used site wide to store thumbnails, previews and temporary files. If none is specified, one will be created using tempfile.mkdtemp()'), help_text=_(
'Temporary directory used site wide to store thumbnails, previews '
'and temporary files. If none is specified, one will be created '
'using tempfile.mkdtemp()'
),
is_path=True is_path=True
) )
setting_shared_storage = namespace.add_setting( setting_shared_storage = namespace.add_setting(
@@ -20,5 +24,7 @@ setting_shared_storage = namespace.add_setting(
setting_paginate_by = namespace.add_setting( setting_paginate_by = namespace.add_setting(
global_name='COMMON_PAGINATE_BY', global_name='COMMON_PAGINATE_BY',
default=40, default=40,
help_text=_('An integer specifying how many objects should be displayed per page.') help_text=_(
'An integer specifying how many objects should be displayed per page.'
)
) )

View File

@@ -100,7 +100,9 @@ def return_attrib(obj, attrib, arguments=None):
try: try:
if isinstance(attrib, types.FunctionType): if isinstance(attrib, types.FunctionType):
return attrib(obj) return attrib(obj)
elif isinstance(obj, types.DictType) or isinstance(obj, types.DictionaryType): elif isinstance(
obj, types.DictType
) or isinstance(obj, types.DictionaryType):
return obj[attrib] return obj[attrib]
else: else:
result = reduce(getattr, attrib.split('.'), obj) result = reduce(getattr, attrib.split('.'), obj)
@@ -140,12 +142,13 @@ def urlquote(link=None, get=None):
assert link or get assert link or get
if isinstance(link, dict): if isinstance(link, dict):
# urlqoute({'key': 'value', 'key2': 'value2'}) --> key=value&key2=value2 # urlqoute({'key': 'value', 'key2': 'value2'}) -->
# key=value&key2=value2
assert not get, get assert not get, get
get = link get = link
link = '' link = ''
assert isinstance(get, dict), 'wrong type "%s", dict required' % type(get) assert isinstance(get, dict), 'wrong type "%s", dict required' % type(get)
# assert not (link.startswith('http://') or link.startswith('https://')), \ # assert not (link.startswith('http://') or link.startswith('https://')),
# 'This method should only quote the url path. # 'This method should only quote the url path.
# It should not start with http(s):// (%s)' % ( # It should not start with http(s):// (%s)' % (
# link) # link)

View File

@@ -12,9 +12,6 @@ from django.utils.http import urlencode
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic import TemplateView from django.views.generic import TemplateView
from documents.search import document_search
from .classes import MissingItem
from .forms import ( from .forms import (
LicenseForm, LocaleProfileForm, LocaleProfileForm_view, LicenseForm, LocaleProfileForm, LocaleProfileForm_view,
UserForm, UserForm_view UserForm, UserForm_view

View File

@@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from itertools import chain
import os import os
from django import forms from django import forms
@@ -107,50 +106,6 @@ class PlainWidget(forms.widgets.Widget):
return mark_safe('%s' % value) return mark_safe('%s' % value)
class ScrollableCheckboxSelectMultiple(forms.widgets.CheckboxSelectMultiple):
"""
Class for a form widget composed of a selection of checkboxes wrapped
in a div tag with automatic overflow to add scrollbars when the list
exceds the height of the div
"""
def render(self, name, value, attrs=None, choices=()):
if value is None:
value = []
has_id = attrs and 'id' in attrs
final_attrs = self.build_attrs(attrs, name=name)
# TODO: Move this styling to a CSS class
output = [
'<ul class="undecorated_list" style="margin-left: 5px; margin-top: 3px; margin-bottom: 3px;">'
]
# Normalize to strings
str_values = set([force_unicode(v) for v in value])
for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
# If an ID attribute was given, add a numeric index as a suffix,
# so that the checkboxes don't all have the same ID attribute.
if has_id:
final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
label_for = ' for="%s"' % final_attrs['id']
else:
label_for = ''
cb = forms.widgets.CheckboxInput(
final_attrs, check_test=lambda value: value in str_values
)
option_value = force_unicode(option_value)
rendered_cb = cb.render(name, option_value)
option_label = conditional_escape(force_unicode(option_label))
output.append(
'<li><label%s>%s %s</label></li>' % (
label_for, rendered_cb, option_label
)
)
output.append('</ul>')
return mark_safe(
'<div class="text_area_div">%s</div>' % '\n'.join(output)
)
class TextAreaDiv(forms.widgets.Widget): class TextAreaDiv(forms.widgets.Widget):
""" """
Class to define a form widget that simulates the behavior of a Class to define a form widget that simulates the behavior of a

View File

@@ -32,7 +32,9 @@ class DjangoGPGTestCase(TestCase):
# Test querying the keyservers # Test querying the keyservers
self.assertTrue( self.assertTrue(
TEST_KEY_ID in [key_stub.key_id for key_stub in self.gpg.query(TEST_UIDS)] TEST_KEY_ID in [
key_stub.key_id for key_stub in self.gpg.query(TEST_UIDS)
]
) )
# Receive a public key from the keyserver # Receive a public key from the keyserver
@@ -40,5 +42,7 @@ class DjangoGPGTestCase(TestCase):
# Check that the received key is indeed in the keyring # Check that the received key is indeed in the keyring
self.assertTrue( self.assertTrue(
TEST_KEY_ID[-16:] in [key_stub.key_id for key_stub in Key.get_all(self.gpg)] TEST_KEY_ID[-16:] in [
key_stub.key_id for key_stub in Key.get_all(self.gpg)
]
) )

View File

@@ -1,6 +1,5 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from datetime import datetime
import logging import logging
from django.conf import settings from django.conf import settings

View File

@@ -51,10 +51,16 @@ def comment_delete(request, comment_id=None, comment_id_list=None):
) )
previous = request.POST.get( previous = request.POST.get(
'previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))) 'previous', request.GET.get(
'previous', request.META.get(
'HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)
)
)
) )
next = request.POST.get( next = request.POST.get(
'next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))) 'next', request.GET.get(
'next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))
)
) )
if request.method == 'POST': if request.method == 'POST':
@@ -110,7 +116,11 @@ def comment_add(request, document_id):
post_action_redirect = None post_action_redirect = None
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))) next = request.POST.get(
'next', request.GET.get(
'next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))
)
)
if request.method == 'POST': if request.method == 'POST':
form = CommentForm(request.POST) form = CommentForm(request.POST)
@@ -144,7 +154,8 @@ class DocumentCommentListView(SingleObjectListView):
) )
except PermissionDenied: except PermissionDenied:
AccessControlList.objects.check_access( AccessControlList.objects.check_access(
permission_comment_view, self.request.user, self.get_document() permission_comment_view, self.request.user,
self.get_document()
) )
return self.get_document().comments.all() return self.get_document().comments.all()

View File

@@ -61,7 +61,8 @@ class DocumentIndexingApp(MayanAppConfig):
) )
) )
SourceColumn( SourceColumn(
source=IndexInstance, label=_('Document types'), attribute='get_document_types_names' source=IndexInstance, label=_('Document types'),
attribute='get_document_types_names'
) )
SourceColumn( SourceColumn(
@@ -74,7 +75,9 @@ class DocumentIndexingApp(MayanAppConfig):
) )
SourceColumn( SourceColumn(
source=IndexTemplateNode, label=_('Has document links?'), source=IndexTemplateNode, label=_('Has document links?'),
func=lambda context: two_state_template(context['object'].link_documents) func=lambda context: two_state_template(
context['object'].link_documents
)
) )
SourceColumn( SourceColumn(

View File

@@ -20,7 +20,8 @@ class IndexInstanceNodeManager(models.Manager):
@staticmethod @staticmethod
def delete_empty_index_nodes_recursive(instance_node): def delete_empty_index_nodes_recursive(instance_node):
""" """
Calls itself recursively deleting empty index instance nodes up to root Calls itself recursively deleting empty index instance nodes up to
root
""" """
if instance_node.get_children().count() == 0: if instance_node.get_children().count() == 0:

View File

@@ -15,11 +15,38 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='Index', name='Index',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
('name', models.CharField(help_text='Internal name used to reference this index.', unique=True, max_length=64, verbose_name='Name')), 'id', models.AutoField(
('title', models.CharField(help_text='The name that will be visible to users.', unique=True, max_length=128, verbose_name='Title')), verbose_name='ID', serialize=False, auto_created=True,
('enabled', models.BooleanField(default=True, help_text='Causes this index to be visible and updated when document data changes.', verbose_name='Enabled')), primary_key=True
('document_types', models.ManyToManyField(to='documents.DocumentType', verbose_name='Document types')), )
),
(
'name', models.CharField(
help_text='Internal name used to reference this index.',
unique=True, max_length=64, verbose_name='Name'
)
),
(
'title', models.CharField(
help_text='The name that will be visible to users.',
unique=True, max_length=128, verbose_name='Title'
)
),
(
'enabled', models.BooleanField(
default=True,
help_text='Causes this index to be visible and updated when document data changes.',
verbose_name='Enabled'
)
),
(
'document_types',
models.ManyToManyField(
to='documents.DocumentType',
verbose_name='Document types'
)
),
], ],
options={ options={
'verbose_name': 'Index', 'verbose_name': 'Index',
@@ -30,13 +57,43 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='IndexInstanceNode', name='IndexInstanceNode',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
('value', models.CharField(max_length=128, verbose_name='Value', blank=True)), 'id', models.AutoField(
('lft', models.PositiveIntegerField(editable=False, db_index=True)), verbose_name='ID', serialize=False, auto_created=True,
('rght', models.PositiveIntegerField(editable=False, db_index=True)), primary_key=True
('tree_id', models.PositiveIntegerField(editable=False, db_index=True)), )
('level', models.PositiveIntegerField(editable=False, db_index=True)), ),
('documents', models.ManyToManyField(related_name='node_instances', verbose_name='Documents', to='documents.Document')), (
'value', models.CharField(
max_length=128, verbose_name='Value', blank=True
)
),
(
'lft', models.PositiveIntegerField(
editable=False, db_index=True
)
),
(
'rght', models.PositiveIntegerField(
editable=False, db_index=True
)
),
(
'tree_id', models.PositiveIntegerField(
editable=False, db_index=True
)
),
(
'level', models.PositiveIntegerField(
editable=False, db_index=True
)
),
(
'documents', models.ManyToManyField(
related_name='node_instances',
verbose_name='Documents', to='documents.Document'
)
),
], ],
options={ options={
'verbose_name': 'Index node instance', 'verbose_name': 'Index node instance',
@@ -47,16 +104,64 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='IndexTemplateNode', name='IndexTemplateNode',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
('expression', models.CharField(help_text='Enter a python string expression to be evaluated.', max_length=128, verbose_name='Indexing expression')), 'id', models.AutoField(
('enabled', models.BooleanField(default=True, help_text='Causes this node to be visible and updated when document data changes.', verbose_name='Enabled')), verbose_name='ID', serialize=False, auto_created=True,
('link_documents', models.BooleanField(default=False, help_text='Check this option to have this node act as a container for documents and not as a parent for further nodes.', verbose_name='Link documents')), primary_key=True
('lft', models.PositiveIntegerField(editable=False, db_index=True)), )
('rght', models.PositiveIntegerField(editable=False, db_index=True)), ),
('tree_id', models.PositiveIntegerField(editable=False, db_index=True)), (
('level', models.PositiveIntegerField(editable=False, db_index=True)), 'expression', models.CharField(
('index', models.ForeignKey(related_name='node_templates', verbose_name='Index', to='document_indexing.Index')), help_text='Enter a python string expression to be evaluated.',
('parent', mptt.fields.TreeForeignKey(blank=True, to='document_indexing.IndexTemplateNode', null=True)), max_length=128, verbose_name='Indexing expression'
)
),
(
'enabled', models.BooleanField(
default=True,
help_text='Causes this node to be visible and updated when document data changes.',
verbose_name='Enabled'
)
),
(
'link_documents', models.BooleanField(
default=False,
help_text='Check this option to have this node act as a container for documents and not as a parent for further nodes.',
verbose_name='Link documents'
)
),
(
'lft', models.PositiveIntegerField(
editable=False, db_index=True
)
),
(
'rght', models.PositiveIntegerField(
editable=False, db_index=True
)
),
(
'tree_id', models.PositiveIntegerField(
editable=False, db_index=True
)
),
(
'level', models.PositiveIntegerField(
editable=False, db_index=True
)
),
(
'index', models.ForeignKey(
related_name='node_templates', verbose_name='Index',
to='document_indexing.Index'
)
),
(
'parent', mptt.fields.TreeForeignKey(
blank=True, to='document_indexing.IndexTemplateNode',
null=True
)
),
], ],
options={ options={
'verbose_name': 'Index node template', 'verbose_name': 'Index node template',
@@ -67,13 +172,20 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='indexinstancenode', model_name='indexinstancenode',
name='index_template_node', name='index_template_node',
field=models.ForeignKey(related_name='node_instance', verbose_name='Index template node', to='document_indexing.IndexTemplateNode'), field=models.ForeignKey(
related_name='node_instance',
verbose_name='Index template node',
to='document_indexing.IndexTemplateNode'
),
preserve_default=True, preserve_default=True,
), ),
migrations.AddField( migrations.AddField(
model_name='indexinstancenode', model_name='indexinstancenode',
name='parent', name='parent',
field=mptt.fields.TreeForeignKey(blank=True, to='document_indexing.IndexInstanceNode', null=True), field=mptt.fields.TreeForeignKey(
blank=True, to='document_indexing.IndexInstanceNode',
null=True
),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -14,7 +14,9 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='index', model_name='index',
name='label', name='label',
field=models.CharField(unique=True, max_length=128, verbose_name='Label'), field=models.CharField(
unique=True, max_length=128, verbose_name='Label'
),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -14,7 +14,11 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='index', model_name='index',
name='slug', name='slug',
field=models.SlugField(null=True, max_length=128, blank=True, help_text='This values will be used by other apps to reference this index.', unique=True, verbose_name='Slug'), field=models.SlugField(
null=True, max_length=128, blank=True,
help_text='This values will be used by other apps to reference this index.',
unique=True, verbose_name='Slug'
),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -14,7 +14,11 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='index', model_name='index',
name='slug', name='slug',
field=models.SlugField(default='', max_length=128, help_text='This values will be used by other apps to reference this index.', unique=True, verbose_name='Slug'), field=models.SlugField(
default='', max_length=128,
help_text='This values will be used by other apps to reference this index.',
unique=True, verbose_name='Slug'
),
preserve_default=False, preserve_default=False,
), ),
] ]

View File

@@ -14,7 +14,10 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='indexinstancenode', model_name='indexinstancenode',
name='value', name='value',
field=models.CharField(db_index=True, max_length=128, verbose_name='Value', blank=True), field=models.CharField(
db_index=True, max_length=128, verbose_name='Value',
blank=True
),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -14,7 +14,10 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='indextemplatenode', model_name='indextemplatenode',
name='expression', name='expression',
field=models.CharField(help_text="Enter a template to render. Use Django's default templating language (https://docs.djangoproject.com/en/1.7/ref/templates/builtins/)", max_length=128, verbose_name='Indexing expression'), field=models.CharField(
help_text="Enter a template to render. Use Django's default templating language (https://docs.djangoproject.com/en/1.7/ref/templates/builtins/)",
max_length=128, verbose_name='Indexing expression'
),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -71,7 +71,9 @@ class Index(models.Model):
def get_document_types_names(self): def get_document_types_names(self):
return ', '.join( return ', '.join(
[unicode(document_type) for document_type in self.document_types.all()] or ['None'] [
unicode(document_type) for document_type in self.document_types.all()
] or ['None']
) )
class Meta: class Meta:

View File

@@ -37,7 +37,8 @@ urlpatterns = patterns(
), ),
url( url(
r'^setup/index/(?P<pk>\d+)/document_types/$', r'^setup/index/(?P<pk>\d+)/document_types/$',
SetupIndexDocumentTypesView.as_view(), name='index_setup_document_types' SetupIndexDocumentTypesView.as_view(),
name='index_setup_document_types'
), ),
url( url(
r'^setup/template/node/(?P<parent_pk>\d+)/create/child/$', r'^setup/template/node/(?P<parent_pk>\d+)/create/child/$',
@@ -84,8 +85,8 @@ api_urls = patterns(
name='index-detail' name='index-detail'
), ),
url( url(
r'^index/(?P<pk>[0-9]+)/template/$', APIIndexTemplateListView.as_view(), r'^index/(?P<pk>[0-9]+)/template/$',
name='index-template-detail' APIIndexTemplateListView.as_view(), name='index-template-detail'
), ),
url(r'^indexes/$', APIIndexListView.as_view(), name='index-list'), url(r'^indexes/$', APIIndexListView.as_view(), name='index-list'),
url( url(

View File

@@ -15,7 +15,6 @@ from common.views import (
AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView, AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectEditView, SingleObjectListView SingleObjectEditView, SingleObjectListView
) )
from common.widgets import two_state_template
from documents.models import Document, DocumentType from documents.models import Document, DocumentType
from documents.permissions import permission_document_view from documents.permissions import permission_document_view
from documents.views import DocumentListView from documents.views import DocumentListView
@@ -33,7 +32,7 @@ from .permissions import (
permission_document_indexing_setup, permission_document_indexing_view permission_document_indexing_setup, permission_document_indexing_view
) )
from .tasks import task_do_rebuild_all_indexes from .tasks import task_do_rebuild_all_indexes
from .widgets import index_instance_item_link, get_breadcrumbs, node_level from .widgets import get_breadcrumbs
# Setup views # Setup views

View File

@@ -21,7 +21,9 @@ def get_instance_link(index_instance_node, text=None, simple=False):
return template % { return template % {
'url': index_instance_node.get_absolute_url(), 'url': index_instance_node.get_absolute_url(),
'value': text if text else (index_instance_node if index_instance_node.parent else index_instance_node.index_template_node.index) 'value': text if text else (
index_instance_node if index_instance_node.parent else index_instance_node.index_template_node.index
)
} }
@@ -50,7 +52,9 @@ def get_breadcrumbs(index_instance_node, simple=False, single_link=False, includ
# Return the entire breadcrumb path as a single HTML anchor # Return the entire breadcrumb path as a single HTML anchor
output.insert( output.insert(
0, get_instance_link( 0, get_instance_link(
index_instance_node=index_instance_node, text=(' / '.join(result)) index_instance_node=index_instance_node, text=(
' / '.join(result)
)
) )
) )
return mark_safe(' '.join(output)) return mark_safe(' '.join(output))
@@ -68,11 +72,13 @@ def index_instance_item_link(index_instance_item):
else: else:
icon_template = '' icon_template = ''
return mark_safe('%(icon_template)s&nbsp;<a href="%(url)s">%(text)s</a>' % { return mark_safe(
'url': index_instance_item.get_absolute_url(), '%(icon_template)s&nbsp;<a href="%(url)s">%(text)s</a>' % {
'icon_template': icon_template, 'url': index_instance_item.get_absolute_url(),
'text': index_instance_item 'icon_template': icon_template,
}) 'text': index_instance_item
}
)
def node_level(node): def node_level(node):
@@ -83,8 +89,9 @@ def node_level(node):
return mark_safe( return mark_safe(
''.join( ''.join(
[ [
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' * (getattr(node, node._mptt_meta.level_attr) - 1), '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' * (
'' if node.is_root_node() else '<i class="fa fa-level-up fa-rotate-90"></i> ', getattr(node, node._mptt_meta.level_attr) - 1
), '' if node.is_root_node() else '<i class="fa fa-level-up fa-rotate-90"></i> ',
ugettext('Root') if node.is_root_node() else unicode(node) ugettext('Root') if node.is_root_node() else unicode(node)
] ]
) )

View File

@@ -103,15 +103,6 @@ class PrintForm(forms.Form):
page_range = forms.CharField(label=_('Page range'), required=False) page_range = forms.CharField(label=_('Page range'), required=False)
class DocumentTypeFilenameForm(forms.ModelForm):
"""
Model class form to edit a document type filename
"""
class Meta:
fields = ('filename', 'enabled')
model = DocumentTypeFilename
class DocumentTypeFilenameForm_create(forms.ModelForm): class DocumentTypeFilenameForm_create(forms.ModelForm):
""" """
Model class form to create a new document type filename Model class form to create a new document type filename

View File

@@ -1 +1 @@
from .literals import * from .literals import * # NOQA

View File

@@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings
from django.core.files import File from django.core.files import File
from django.test import TestCase from django.test import TestCase

View File

@@ -21,8 +21,7 @@ from common.generics import (
SingleObjectEditView, SingleObjectListView SingleObjectEditView, SingleObjectListView
) )
from common.mixins import MultipleInstanceActionMixin from common.mixins import MultipleInstanceActionMixin
from common.utils import encapsulate, pretty_size from common.utils import pretty_size
from common.widgets import two_state_template
from converter.literals import ( from converter.literals import (
DEFAULT_PAGE_NUMBER, DEFAULT_ROTATION, DEFAULT_ZOOM_LEVEL DEFAULT_PAGE_NUMBER, DEFAULT_ROTATION, DEFAULT_ZOOM_LEVEL
) )
@@ -36,8 +35,8 @@ from .events import (
) )
from .forms import ( from .forms import (
DocumentDownloadForm, DocumentForm, DocumentPageForm, DocumentPreviewForm, DocumentDownloadForm, DocumentForm, DocumentPageForm, DocumentPreviewForm,
DocumentPropertiesForm, DocumentTypeFilenameForm, DocumentPropertiesForm, DocumentTypeSelectForm,
DocumentTypeFilenameForm_create, DocumentTypeSelectForm, PrintForm DocumentTypeFilenameForm_create, PrintForm
) )
from .literals import DOCUMENT_IMAGE_TASK_TIMEOUT from .literals import DOCUMENT_IMAGE_TASK_TIMEOUT
from .models import ( from .models import (

View File

@@ -8,7 +8,7 @@ from rest_api.filters import MayanObjectPermissionsFilter
from .classes import SearchModel from .classes import SearchModel
from .filters import RecentSearchUserFilter from .filters import RecentSearchUserFilter
from .models import RecentSearch from .models import RecentSearch
from .serializers import RecentSearchSerializer, SearchSerializer from .serializers import RecentSearchSerializer
class APIRecentSearchListView(generics.ListAPIView): class APIRecentSearchListView(generics.ListAPIView):

View File

@@ -15,7 +15,3 @@ class RecentSearchSerializer(serializers.HyperlinkedModelSerializer):
fields = ('datetime_created', 'hits', 'query', 'url', 'user') fields = ('datetime_created', 'hits', 'query', 'url', 'user')
model = RecentSearch model = RecentSearch
read_only_fields = ('datetime_created', 'hits', 'query', 'user') read_only_fields = ('datetime_created', 'hits', 'query', 'user')
class SearchSerializer(serializers.Serializer):
results = serializers.CharField()

View File

@@ -6,8 +6,6 @@ import urlparse
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.generics import SimpleView, SingleObjectListView from common.generics import SimpleView, SingleObjectListView

View File

@@ -20,7 +20,8 @@ class EventsApp(MayanAppConfig):
SourceColumn(source=Action, label=_('Timestamp'), attribute='timestamp') SourceColumn(source=Action, label=_('Timestamp'), attribute='timestamp')
SourceColumn(source=Action, label=_('Actor'), attribute='actor') SourceColumn(source=Action, label=_('Actor'), attribute='actor')
SourceColumn(source=Action, label=_('Verb'), SourceColumn(
source=Action, label=_('Verb'),
func=lambda context: event_type_link(context['object']) func=lambda context: event_type_link(context['object'])
) )

View File

@@ -1,11 +1,8 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.generics import SingleObjectListView from common.generics import SingleObjectListView
from permissions import Permission
from .classes import PropertyNamespace from .classes import PropertyNamespace
from .permissions import permission_installation_details from .permissions import permission_installation_details
@@ -37,4 +34,3 @@ class NamespaceDetailView(SingleObjectListView):
def get_queryset(self): def get_queryset(self):
return self.get_namespace().get_properties() return self.get_namespace().get_properties()

View File

@@ -16,7 +16,6 @@ from common.generics import (
AssignRemoveView, SingleObjectCreateView, SingleObjectEditView, AssignRemoveView, SingleObjectCreateView, SingleObjectEditView,
SingleObjectListView SingleObjectListView
) )
from common.widgets import two_state_template
from documents.models import Document, DocumentType from documents.models import Document, DocumentType
from documents.permissions import permission_document_view from documents.permissions import permission_document_view
from documents.views import DocumentListView from documents.views import DocumentListView

View File

@@ -11,7 +11,7 @@ from fuse import FUSE, FuseOSError, Operations
from django.core import management from django.core import management
from django.core.cache import caches from django.core.cache import caches
from django.core.exceptions import MultipleObjectsReturned from django.core.exceptions import MultipleObjectsReturned
from django.db.models import Count, Max from django.db.models import Count
from document_indexing.models import Index, IndexInstanceNode from document_indexing.models import Index, IndexInstanceNode
from documents.models import Document from documents.models import Document

View File

@@ -32,8 +32,14 @@ class UserManagementApp(MayanAppConfig):
APIEndPoint(app=self, version_string='1') APIEndPoint(app=self, version_string='1')
MetadataLookup(description=_('All the groups.'), name='group', value=Group.objects.all()) MetadataLookup(
MetadataLookup(description=_('All the users.'), name='users', value=get_user_model().objects.all()) description=_('All the groups.'), name='group',
value=Group.objects.all()
)
MetadataLookup(
description=_('All the users.'), name='users',
value=get_user_model().objects.all()
)
SourceColumn( SourceColumn(
source=Group, label=_('Members'), attribute='user_set.count' source=Group, label=_('Members'), attribute='user_set.count'
@@ -47,11 +53,15 @@ class UserManagementApp(MayanAppConfig):
) )
SourceColumn( SourceColumn(
source=User, label=_('Active'), source=User, label=_('Active'),
func=lambda context: two_state_template(context['object'].is_active) func=lambda context: two_state_template(
context['object'].is_active
)
) )
SourceColumn( SourceColumn(
source=User, label=_('Has usable password?'), source=User, label=_('Has usable password?'),
func=lambda context: two_state_template(context['object'].has_usable_password()) func=lambda context: two_state_template(
context['object'].has_usable_password()
)
) )
menu_multi_item.bind_links( menu_multi_item.bind_links(

View File

@@ -14,7 +14,6 @@ from common.views import (
AssignRemoveView, SingleObjectCreateView, SingleObjectEditView, AssignRemoveView, SingleObjectCreateView, SingleObjectEditView,
SingleObjectListView SingleObjectListView
) )
from common.widgets import two_state_template
from permissions import Permission from permissions import Permission
from .forms import PasswordForm, UserForm from .forms import PasswordForm, UserForm
@@ -47,7 +46,10 @@ def user_edit(request, user_id):
if user.is_superuser or user.is_staff: if user.is_superuser or user.is_staff:
messages.error( messages.error(
request, request,
_('Super user and staff user editing is not allowed, use the admin interface for these cases.') _(
'Super user and staff user editing is not allowed, use the '
'admin interface for these cases.'
)
) )
return HttpResponseRedirect( return HttpResponseRedirect(
request.META.get( request.META.get(
@@ -106,7 +108,9 @@ def user_delete(request, user_id=None, user_id_list=None):
post_action_redirect = reverse('user_management:user_list') post_action_redirect = reverse('user_management:user_list')
elif user_id_list: elif user_id_list:
users = [ users = [
get_object_or_404(User, pk=user_id) for user_id in user_id_list.split(',') get_object_or_404(
User, pk=user_id
) for user_id in user_id_list.split(',')
] ]
else: else:
messages.error(request, _('Must provide at least one user.')) messages.error(request, _('Must provide at least one user.'))
@@ -123,14 +127,24 @@ def user_delete(request, user_id=None, user_id_list=None):
for user in users: for user in users:
try: try:
if user.is_superuser or user.is_staff: if user.is_superuser or user.is_staff:
messages.error(request, _('Super user and staff user deleting is not allowed, use the admin interface for these cases.')) messages.error(
request,
_(
'Super user and staff user deleting is not '
'allowed, use the admin interface for these cases.'
)
)
else: else:
user.delete() user.delete()
messages.success(request, _('User "%s" deleted successfully.') % user) messages.success(
request, _('User "%s" deleted successfully.') % user
)
except Exception as exception: except Exception as exception:
messages.error(request, _('Error deleting user "%(user)s": %(error)s') % { messages.error(
'user': user, 'error': exception request, _('Error deleting user "%(user)s": %(error)s') % {
}) 'user': user, 'error': exception
}
)
return HttpResponseRedirect(next) return HttpResponseRedirect(next)
@@ -145,8 +159,10 @@ def user_delete(request, user_id=None, user_id_list=None):
elif len(users) > 1: elif len(users) > 1:
context['title'] = _('Delete the users: %s?') % ', '.join([unicode(d) for d in users]) context['title'] = _('Delete the users: %s?') % ', '.join([unicode(d) for d in users])
return render_to_response('appearance/generic_confirm.html', context, return render_to_response(
context_instance=RequestContext(request)) 'appearance/generic_confirm.html', context,
context_instance=RequestContext(request)
)
def user_multiple_delete(request): def user_multiple_delete(request):
@@ -166,7 +182,11 @@ def user_set_password(request, user_id=None, user_id_list=None):
users = [get_object_or_404(User, pk=user_id) for user_id in user_id_list.split(',')] users = [get_object_or_404(User, pk=user_id) for user_id in user_id_list.split(',')]
else: else:
messages.error(request, _('Must provide at least one user.')) messages.error(request, _('Must provide at least one user.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))) return HttpResponseRedirect(
request.META.get(
'HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)
)
)
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))) next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
@@ -181,15 +201,30 @@ def user_set_password(request, user_id=None, user_id_list=None):
for user in users: for user in users:
try: try:
if user.is_superuser or user.is_staff: if user.is_superuser or user.is_staff:
messages.error(request, _('Super user and staff user password reseting is not allowed, use the admin interface for these cases.')) messages.error(
request,
_(
'Super user and staff user password '
'reseting is not allowed, use the admin '
'interface for these cases.'
)
)
else: else:
user.set_password(password_1) user.set_password(password_1)
user.save() user.save()
messages.success(request, _('Successfull password reset for user: %s.') % user) messages.success(
request, _(
'Successfull password reset for user: %s.'
) % user
)
except Exception as exception: except Exception as exception:
messages.error(request, _('Error reseting password for user "%(user)s": %(error)s') % { messages.error(
'user': user, 'error': exception request, _(
}) 'Error reseting password for user "%(user)s": %(error)s'
) % {
'user': user, 'error': exception
}
)
return HttpResponseRedirect(next) return HttpResponseRedirect(next)
else: else:
@@ -243,10 +278,14 @@ class UserGroupsView(AssignRemoveView):
return get_object_or_404(User, pk=self.kwargs['pk']) return get_object_or_404(User, pk=self.kwargs['pk'])
def left_list(self): def left_list(self):
return AssignRemoveView.generate_choices(get_user_non_groups(self.get_object())) return AssignRemoveView.generate_choices(
get_user_non_groups(self.get_object())
)
def right_list(self): def right_list(self):
return AssignRemoveView.generate_choices(get_user_groups(self.get_object())) return AssignRemoveView.generate_choices(
get_user_groups(self.get_object())
)
def remove(self, item): def remove(self, item):
item.user_set.remove(self.get_object()) item.user_set.remove(self.get_object())
@@ -297,7 +336,9 @@ def group_delete(request, group_id=None, group_id_list=None):
groups = [get_object_or_404(Group, pk=group_id)] groups = [get_object_or_404(Group, pk=group_id)]
post_action_redirect = reverse('user_management:group_list') post_action_redirect = reverse('user_management:group_list')
elif group_id_list: elif group_id_list:
groups = [get_object_or_404(Group, pk=group_id) for group_id in group_id_list.split(',')] groups = [
get_object_or_404(Group, pk=group_id) for group_id in group_id_list.split(',')
]
else: else:
messages.error(request, _('Must provide at least one group.')) messages.error(request, _('Must provide at least one group.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))) return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))
@@ -359,10 +400,16 @@ class GroupMembersView(AssignRemoveView):
return get_object_or_404(Group, pk=self.kwargs['pk']) return get_object_or_404(Group, pk=self.kwargs['pk'])
def left_list(self): def left_list(self):
return AssignRemoveView.generate_choices(User.objects.exclude(groups=self.get_object()).exclude(is_staff=True).exclude(is_superuser=True)) return AssignRemoveView.generate_choices(
User.objects.exclude(
groups=self.get_object()
).exclude(is_staff=True).exclude(is_superuser=True)
)
def right_list(self): def right_list(self):
return AssignRemoveView.generate_choices(self.get_object().user_set.all()) return AssignRemoveView.generate_choices(
self.get_object().user_set.all()
)
def remove(self, item): def remove(self, item):
self.get_object().user_set.remove(item) self.get_object().user_set.remove(item)