diff options
Diffstat (limited to 'ishtar_common')
-rw-r--r-- | ishtar_common/forms_common.py | 53 | ||||
-rw-r--r-- | ishtar_common/ishtar_menu.py | 13 | ||||
-rw-r--r-- | ishtar_common/models.py | 3 | ||||
-rw-r--r-- | ishtar_common/urls.py | 8 | ||||
-rw-r--r-- | ishtar_common/views.py | 64 | ||||
-rw-r--r-- | ishtar_common/widgets.py | 4 | ||||
-rw-r--r-- | ishtar_common/wizards.py | 5 |
7 files changed, 130 insertions, 20 deletions
diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 1d8dc2092..a9873cb0a 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2010-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -306,6 +306,51 @@ class SimplePersonForm(NewItemForm): self.fields['raw_name'].widget.attrs['readonly'] = True +class PersonUserSelect(PersonSelect): + ishtaruser__isnull = forms.NullBooleanField( + label=_(u"Already has an account"), initial=False) + + +class PersonUserFormSelection(PersonFormSelection): + form_label = _(u"Person search") + associated_models = {'pk': models.Person} + currents = {'pk': models.Person} + pk = forms.IntegerField( + label="", + widget=widgets.JQueryJqGrid(reverse_lazy('get-person'), + PersonUserSelect, models.Person), + validators=[models.valid_id(models.Person)]) + + +class IshtarUserSelect(TableSelect): + username = forms.CharField(label=_(u"Username"), max_length=200) + name = forms.CharField(label=_(u"Name"), max_length=200) + surname = forms.CharField(label=_(u"Surname"), max_length=50) + email = forms.CharField(label=_(u"Email"), max_length=75) + person_types = forms.ChoiceField(label=_(u"Type"), choices=[]) + attached_to = forms.IntegerField( + label=_("Organization"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-organization'), + associated_model=models.Organization), + validators=[models.valid_id(models.Organization)]) + + def __init__(self, *args, **kwargs): + super(IshtarUserSelect, self).__init__(*args, **kwargs) + self.fields['person_types'].choices = models.PersonType.get_types() + + +class AccountFormSelection(forms.Form): + form_label = _(u"Account search") + associated_models = {'pk': models.IshtarUser} + currents = {'pk': models.IshtarUser} + pk = forms.IntegerField( + label="", + widget=widgets.JQueryJqGrid(reverse_lazy('get-ishtaruser'), + IshtarUserSelect, models.IshtarUser), + validators=[models.valid_id(models.IshtarUser)]) + + class BasePersonForm(forms.ModelForm): class Meta: model = models.Person @@ -427,11 +472,11 @@ class AccountForm(forms.Form): raise forms.ValidationError(_(u"You must provide a correct " u"password.")) # check username unicity - usernames = models.IshtarUser.objects.filter( + q = models.IshtarUser.objects.filter( username=cleaned_data.get('username')) if cleaned_data.get('pk'): - usernames.exclude(pk=cleaned_data.get('pk')) - if usernames.count(): + q = q.exclude(person__pk=cleaned_data.get('pk')) + if q.count(): raise forms.ValidationError(_(u"This username already exists.")) return cleaned_data diff --git a/ishtar_common/ishtar_menu.py b/ishtar_common/ishtar_menu.py index 30cba6735..39bf7c1d6 100644 --- a/ishtar_common/ishtar_menu.py +++ b/ishtar_common/ishtar_menu.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2010-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -28,9 +28,14 @@ import models MENU_SECTIONS = [ (5, SectionItem('admin', _(u"Administration"), childs=[ - MenuItem('account_management', _(u"Account management"), - model=models.IshtarUser, - access_controls=['add_ishtaruser', ]), + SectionItem( + 'account', _(u"Account"), + childs=[MenuItem('account_management', _(u"Add/modify"), + model=models.IshtarUser, + access_controls=['add_ishtaruser', ]), + MenuItem('account_deletion', _(u"Deletion"), + model=models.IshtarUser, + access_controls=['add_ishtaruser', ]), ]), MenuItem('admin-globalvar', _(u"Global variables"), model=models.GlobalVar, access_controls=['add_globalvar', ]), diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 3c46573dd..a4d7f70d9 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -2336,6 +2336,9 @@ class Person(Address, Merge, OwnPerms, ValueGetter): class IshtarUser(User): + TABLE_COLS = ('username', 'person__name', 'person__surname', + 'person__email', 'person__person_types_list', + 'person__attached_to') person = models.ForeignKey(Person, verbose_name=_(u"Person"), unique=True, related_name='ishtaruser') diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index a3bcaffb5..30b5741d9 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2010-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -81,9 +81,15 @@ urlpatterns = patterns( check_rights(['change_organization', 'change_own_organization'])( views.OrganizationPersonEdit.as_view()), name='organization_person_edit'), + url(r'get-ishtaruser/(?P<type>.+)?$', + views.get_ishtaruser, + name='get-ishtaruser'), url(r'account_management/(?P<step>.+)?$', check_rights(['add_ishtaruser'])( views.account_management_wizard), name='account_management'), + url(r'account_deletion/(?P<step>.+)?$', + check_rights(['add_ishtaruser'])( + views.account_deletion_wizard), name='account_deletion'), url(r'^import-new/$', check_rights(['change_import'])( views.NewImportView.as_view()), name='new_import'), diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 2d0976be1..01811ed2d 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -38,6 +38,7 @@ from django.contrib.auth.decorators import login_required from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse, NoReverseMatch from django.db.models import Q, ImageField +from django.db.models.fields import FieldDoesNotExist from django.forms.models import modelformset_factory from django.http import HttpResponse, Http404, HttpResponseRedirect, \ HttpResponseBadRequest @@ -148,12 +149,18 @@ organization_deletion_wizard = wizards.OrganizationDeletionWizard.as_view( url_name='organization_deletion',) account_management_wizard = wizards.AccountWizard.as_view( - [('selec-account_management', forms.PersonFormSelection), + [('selec-account_management', forms.PersonUserFormSelection), ('account-account_management', forms.AccountForm), ('final-account_management', forms.FinalAccountForm)], label=_(u"Account management"), url_name='account_management',) +account_deletion_wizard = wizards.IshtarUserDeletionWizard.as_view( + [('selec-account_deletion', forms.AccountFormSelection), + ('final-account_deletion', FinalDeleteForm)], + label=_(u"Account deletion"), + url_name='account_deletion',) + def get_autocomplete_generic(model, extra={'available': True}): def func(request): @@ -447,14 +454,19 @@ def get_item(model, func_name, default_name, extra_request_keys=[], if k in reversed_bool_fields: dct[k] = not dct[k] # check also for empty value with image field - c_field = model._meta.get_field(k.split('__')[0]) - if k.endswith('__isnull') and \ - isinstance(c_field, ImageField): - if dct[k]: - or_reqs.append( - (k, {k.split('__')[0] + '__exact': ''})) - else: - dct[k.split('__')[0] + '__regex'] = '.{1}.*' + field_name = k.split('__')[0] + # TODO: can be improved in later evrsion of Django + try: + c_field = model._meta.get_field(field_name) + if k.endswith('__isnull') and \ + isinstance(c_field, ImageField): + if dct[k]: + or_reqs.append( + (k, {k.split('__')[0] + '__exact': ''})) + else: + dct[k.split('__')[0] + '__regex'] = '.{1}.*' + except FieldDoesNotExist: + pass for k in dated_fields: if k in dct: if not dct[k]: @@ -527,6 +539,7 @@ def get_item(model, func_name, default_name, extra_request_keys=[], query = query & and_req items = model.objects.filter(query).distinct() + # print(items.query) q = request_items.get('sidx') # table cols @@ -614,7 +627,14 @@ def get_item(model, func_name, default_name, extra_request_keys=[], my_vals = [] for k in keys: vals = [item] + # foreign key may be splited by "." or "__" + splitted_k = [] for ky in k.split('.'): + if '__' in ky: + splitted_k += ky.split('__') + else: + splitted_k.append(ky) + for ky in splitted_k: new_vals = [] for val in vals: if hasattr(val, 'all'): # manage related objects @@ -685,7 +705,16 @@ def get_item(model, func_name, default_name, extra_request_keys=[], table_col = table_cols[idx] if type(table_col) not in (list, tuple): table_col = [table_col] - k = "__".join([tc.split('.')[-1] for tc in table_col]) + tab_cols = [] + # foreign key may be splited by "." or "__" + for tc in table_col: + if '.' in tc: + tab_cols.append(tc.split('.')[-1]) + elif '__' in tc: + tab_cols.append(tc.split('__')[-1]) + else: + tab_cols.append(tc) + k = "__".join(tab_cols) res[k] = value rows.append(res) data = json.dumps({ @@ -941,11 +970,26 @@ show_person = show_item(models.Person, 'person') get_person = get_item( models.Person, 'get_person', 'person', + reversed_bool_fields=['ishtaruser__isnull'], extra_request_keys={ 'name': ['name__icontains', 'raw_name__icontains'], 'surname': ['surname__icontains', 'raw_name__icontains'], 'attached_to': 'attached_to__pk', 'person_types': 'person_types__pk__in', + 'ishtaruser__isnull': 'ishtaruser__isnull' + }) + +get_ishtaruser = get_item( + models.IshtarUser, + 'get_ishtaruser', 'ishtaruser', + extra_request_keys={ + 'username': ['username__icontains'], + 'name': ['person__name__icontains', 'person__raw_name__icontains'], + 'surname': ['person__surname__icontains', + 'person__raw_name__icontains'], + 'email': ['person__email'], + 'attached_to': 'person__attached_to__pk', + 'person_types': 'person__person_types__pk__in', }) diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 6d9600d0c..83fb23caf 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -539,7 +539,9 @@ class JQueryJqGrid(forms.RadioSelect): col_names = [col_names] for col_name in col_names: field = self.associated_model - keys = col_name.split('.') + keys = col_name.split('__') + if '.' in col_name: + keys = col_name.split('.') f_name = '' for key in keys: if hasattr(field, 'rel') and field.rel: diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index 97bb6fb37..f028c15d8 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -1132,6 +1132,11 @@ class PersonDeletionWizard(DeletionWizard): 'final-person_deletion': 'ishtar/wizard/wizard_person_deletion.html'} +class IshtarUserDeletionWizard(DeletionWizard): + model = models.IshtarUser + fields = model.TABLE_COLS + + class OrganizationWizard(Wizard): model = models.Organization |