diff options
| -rw-r--r-- | ishtar_common/admin.py | 87 | ||||
| -rw-r--r-- | ishtar_common/forms.py | 27 | ||||
| -rw-r--r-- | ishtar_common/models.py | 48 | ||||
| -rw-r--r-- | ishtar_common/utils.py | 6 | 
4 files changed, 151 insertions, 17 deletions
| diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index 8045bff13..7c21fa4be 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -32,6 +32,7 @@ from django.contrib.sites.admin import SiteAdmin  from django.contrib.sites.models import Site  from django.contrib.gis.forms import PointField, OSMWidget, MultiPolygonField  from django.core.cache import cache +from django.forms import BaseInlineFormSet  from django.http import HttpResponseRedirect, HttpResponse  from django.shortcuts import render  from django.template.defaultfilters import slugify @@ -91,6 +92,7 @@ def gen_import_generic(self, request, queryset):                       request.POST.getlist(admin.ACTION_CHECKBOX_NAME)})      return render(request, 'admin/import_from_csv.html', {'csv_form': form}) +  gen_import_generic.short_description = "Import from a CSV file" @@ -166,6 +168,7 @@ class IshtarSiteProfileAdmin(admin.ModelAdmin):                      'find', 'warehouse', 'mapping', 'preservation')      model = models.IshtarSiteProfile +  admin_site.register(models.IshtarSiteProfile, IshtarSiteProfileAdmin) @@ -173,6 +176,7 @@ class DepartmentAdmin(admin.ModelAdmin):      list_display = ('number', 'label',)      model = models.Department +  admin_site.register(models.Department, DepartmentAdmin) @@ -183,6 +187,7 @@ class OrganizationAdmin(HistorizedObjectAdmin):      exclude = ('merge_key', 'merge_exclusion', 'merge_candidate', )      model = models.Organization +  admin_site.register(models.Organization, OrganizationAdmin) @@ -194,6 +199,7 @@ class PersonAdmin(HistorizedObjectAdmin):      form = make_ajax_form(models.Person, {'attached_to': 'organization'})      model = models.Person +  admin_site.register(models.Person, PersonAdmin) @@ -251,6 +257,7 @@ class AuthorAdmin(admin.ModelAdmin):      model = models.Author      form = make_ajax_form(models.Author, {'person': 'person'}) +  admin_site.register(models.Author, AuthorAdmin) @@ -259,11 +266,14 @@ class PersonTypeAdmin(admin.ModelAdmin):      model = models.PersonType      filter_vertical = ('groups',) +  admin_site.register(models.PersonType, PersonTypeAdmin)  class GlobalVarAdmin(admin.ModelAdmin):      list_display = ['slug', 'description', 'value'] + +  admin_site.register(models.GlobalVar, GlobalVarAdmin) @@ -290,16 +300,22 @@ class ImporterDefaultAdmin(admin.ModelAdmin):      list_display = ('importer_type', 'target')      model = models.ImporterDefault      inlines = (ImporterDefaultValuesInline,) + +  admin_site.register(models.ImporterDefault, ImporterDefaultAdmin)  class ImporterTypeAdmin(admin.ModelAdmin):      list_display = ('name', 'associated_models', 'available') + +  admin_site.register(models.ImporterType, ImporterTypeAdmin)  class RegexpAdmin(admin.ModelAdmin):      list_display = ('name', 'description', "regexp") + +  admin_site.register(models.Regexp, RegexpAdmin) @@ -327,6 +343,8 @@ class ImporterColumnAdmin(admin.ModelAdmin):                      'targets_lbl', 'duplicate_fields_lbl', 'required')      list_filter = ('importer_type',)      inlines = (ImportTargetInline, ImporterDuplicateFieldInline) + +  admin_site.register(models.ImporterColumn, ImporterColumnAdmin) @@ -392,6 +410,8 @@ admin_site.register(models.SpatialReferenceSystem, SpatialReferenceSystemAdmin)  class ItemKeyAdmin(admin.ModelAdmin):      list_display = ('content_type', 'key', 'content_object', 'importer')      search_fields = ('key', ) + +  admin_site.register(models.ItemKey, ItemKeyAdmin) @@ -449,18 +469,10 @@ def get_choices_form():      cache_key, value = get_cache(models.CustomForm, ['associated-forms'])      if value:          return value -    forms = set() -    for app_form in ISHTAR_FORMS: -        for form in dir(app_form): -            if 'Form' not in form: -                # not very clean... but do not treat inappropriate items -                continue -            form = getattr(app_form, form) -            if not issubclass(form, common_forms.CustomForm)\ -                    or not getattr(form, 'form_slug', None): -                continue -            forms.add((form.form_slug, form.form_admin_name)) -    forms = list(forms) +    forms = [] +    for slug in models.CustomForm.register(): +        forms.append((slug, models.CustomForm._register[slug].form_admin_name)) +    forms = sorted(forms, key=lambda x: x[1])      cache.set(cache_key, forms, settings.CACHE_TIMEOUT)      return forms @@ -474,9 +486,57 @@ class CustomFormForm(forms.ModelForm):                                              label=_(u"Users")) +class ExcludeFieldFormset(BaseInlineFormSet): +    def get_form_kwargs(self, index): +        kwargs = super(ExcludeFieldFormset, self).get_form_kwargs(index) +        if not self.instance or not self.instance.pk: +            return kwargs +        form = self.instance.get_form_class() +        if not form: +            kwargs['choices'] = [] +            return kwargs +        kwargs['choices'] = [('', '--')] + form.get_custom_fields() +        return kwargs + + +class ExcludeFieldForm(forms.ModelForm): +    class Meta: +        model = models.ExcludedField +        exclude = [] +    field = forms.ChoiceField(label=_(u"Field")) + +    def __init__(self, *args, **kwargs): +        choices = kwargs.pop('choices') +        super(ExcludeFieldForm, self).__init__(*args, **kwargs) +        self.fields['field'].choices = choices + + +class ExcludeFieldInline(admin.TabularInline): +    model = models.ExcludedField +    extra = 2 +    form = ExcludeFieldForm +    formset = ExcludeFieldFormset + +  class CustomFormAdmin(admin.ModelAdmin): -    list_display = ['name', 'form', 'available'] +    list_display = ['name', 'form', 'available', 'apply_to_all', +                    'users_lbl', 'user_types_lbl'] +    fields = ('name', 'form', 'available', 'apply_to_all', 'users', +              'user_types')      form = CustomFormForm +    inlines = [ExcludeFieldInline] + +    def get_inline_instances(self, request, obj=None): +        # no inline on creation +        if not obj: +            return [] +        return super(CustomFormAdmin, self).get_inline_instances(request, +                                                                 obj=obj) + +    def get_readonly_fields(self, request, obj=None): +        if obj: +            return ('form',) +        return []  admin_site.register(models.CustomForm, CustomFormAdmin) @@ -515,6 +575,7 @@ class AdministrationTaskAdmin(admin.ModelAdmin):              return ("script", ) + self.readonly_fields          return self.readonly_fields +  admin_site.register(models.AdministrationTask, AdministrationTaskAdmin) diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index d0c2bb035..0f1fa20f8 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -302,6 +302,33 @@ class CustomForm(object):      form_admin_name = ""      form_slug = "" +    def __init__(self, *args, **kwargs): +        super(CustomForm, self).__init__(*args, **kwargs) +        # todo: filter by user / group... +        q = models.CustomForm.objects.filter(form=self.form_slug, +                                             available=True, apply_to_all=True) +        if not q.count(): +            return +        # todo: prevent multiple result in database +        form = q.all()[0] +        for excluded in form.excluded_fields.all(): +            # could have be filtered previously +            if excluded.field in self.fields: +                self.fields.pop(excluded.field) + +    @classmethod +    def get_custom_fields(cls): +        fields = cls.base_fields +        customs = [] +        for key in fields: +            field = fields[key] +            # cannot customize display of required and hidden field +            # field with no label are also rejected +            if field.required or field.widget.is_hidden or not field.label: +                continue +            customs.append((key, field.label)) +        return sorted(customs, key=lambda x: x[1]) +  class DocumentGenerationForm(forms.Form):      """ diff --git a/ishtar_common/models.py b/ishtar_common/models.py index a5a3d96c1..c888e87fd 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -1647,14 +1647,58 @@ class CustomForm(models.Model):          verbose_name_plural = _(u"Custom forms")          ordering = ['name', 'form'] +    def users_lbl(self): +        users = [unicode(user) for user in self.users.all()] +        return " ; ".join(users) + +    users_lbl.short_description = _(u"Users") + +    def user_types_lbl(self): +        user_types = [unicode(u) for u in self.user_types.all()] +        return " ; ".join(user_types) + +    user_types_lbl.short_description = _(u"User types") + +    @classmethod +    def register(cls): +        if hasattr(cls, '_register'): +            return cls._register +        cache_key, value = get_cache(cls.__class__, ['dct-forms'], +                                     app_label='ishtar_common') +        if value: +            cls._register = value +            return cls._register +        cls._register = {} +        # ideally should be improved but only used in admin +        from ishtar_common.admin import ISHTAR_FORMS +        from ishtar_common.forms import CustomForm + +        for app_form in ISHTAR_FORMS: +            for form in dir(app_form): +                if 'Form' not in form: +                    # not very clean... but do not treat inappropriate items +                    continue +                form = getattr(app_form, form) +                if not issubclass(form, CustomForm) \ +                        or not getattr(form, 'form_slug', None): +                    continue +                cls._register[form.form_slug] = form +        return cls._register + +    def get_form_class(self): +        register = self.register() +        if self.form not in self._register: +            return +        return register[self.form] +  class ExcludedField(models.Model):      custom_form = models.ForeignKey(CustomForm, related_name='excluded_fields')      field = models.CharField(_(u"Field"), max_length=250)      class Meta: -        verbose_name = _(u"Custom form - excluded field") -        verbose_name_plural = _(u"Custom form - excluded fields") +        verbose_name = _(u"Excluded field") +        verbose_name_plural = _(u"Excluded fields")  class GlobalVar(models.Model, Cached): diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 5d9e85c60..ae178a752 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -51,9 +51,11 @@ def get_current_year():      return datetime.datetime.now().year -def get_cache(cls, extra_args=[]): +def get_cache(cls, extra_args=tuple(), app_label=None): +    if not app_label: +        app_label = cls._meta.app_label      cache_key = u"{}-{}-{}".format( -        settings.PROJECT_SLUG, cls._meta.app_label, cls.__name__) +        settings.PROJECT_SLUG, app_label, cls.__name__)      for arg in extra_args:          if not arg:              cache_key += '-0' | 
