diff options
| author | Étienne Loks <etienne.loks@proxience.com> | 2015-08-19 15:12:43 +0200 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@proxience.com> | 2015-08-19 15:12:43 +0200 | 
| commit | ab53d8cfdcfbbaff8cc5b6bc0e44ee923485d9bb (patch) | |
| tree | 840ab617f2927fec8143f6005cfd2d498d1c738f /ishtar_common/forms_common.py | |
| parent | b4a8dcb2836c202edf250c9953327a9ca5280004 (diff) | |
| download | Ishtar-ab53d8cfdcfbbaff8cc5b6bc0e44ee923485d9bb.tar.bz2 Ishtar-ab53d8cfdcfbbaff8cc5b6bc0e44ee923485d9bb.zip  | |
Archaeological files: change planning service management
Diffstat (limited to 'ishtar_common/forms_common.py')
| -rw-r--r-- | ishtar_common/forms_common.py | 268 | 
1 files changed, 158 insertions, 110 deletions
diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 509b9fbc5..b2aa565bb 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -20,19 +20,14 @@  """  Administrative forms definitions: manage accounts and persons  """ -import datetime  from django import forms  from django.conf import settings  from django.contrib.auth.models import User -from django.contrib.sites.models import Site  from django.core import validators -from django.core.exceptions import ObjectDoesNotExist, ValidationError -from django.core.mail import send_mail -from django.forms.formsets import formset_factory, DELETION_FIELD_NAME +from django.core.exceptions import ObjectDoesNotExist +from django.forms.formsets import formset_factory  from django.forms.models import BaseModelFormSet -from django.template import Context, RequestContext, loader -from django.shortcuts import render_to_response  from django.utils.safestring import mark_safe  from django.utils.translation import ugettext_lazy as _ @@ -40,27 +35,33 @@ import models  import widgets  from forms import FinalForm, FormSet, reverse_lazy, name_validator, TableSelect +  def get_town_field(label=_(u"Town"), required=True): -    help_text = _(u"<p>Type name, department code and/or postal code of the " -    u"town you would like to select. The search is insensitive to case.</p>\n" -    u"<p>Only the first twenty results are displayed but specifying the " -    u"department code is generally sufficient to get the appropriate result.</p>" -    u"\n<p class='example'>For instance type \"saint denis 93\" for getting " -    u"the french town Saint-Denis in the Seine-Saint-Denis department.</p>") +    help_text = _( +        u"<p>Type name, department code and/or postal code of the " +        u"town you would like to select. The search is insensitive to case." +        u"</p>\n<p>Only the first twenty results are displayed but specifying " +        u"the department code is generally sufficient to get the appropriate " +        u"result.</p>\n<p class='example'>For instance type \"saint denis 93\"" +        u" for getting the french town Saint-Denis in the Seine-Saint-Denis " +        u"department.</p>")      # !FIXME hard_link, reverse_lazy doen't seem to work with formsets      return forms.IntegerField( -         widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ -                     'autocomplete-town', associated_model=models.Town), -         validators=[models.valid_id(models.Town)], label=label, -         help_text=mark_safe(help_text), required=required) +        widget=widgets.JQueryAutoComplete( +            "/" + settings.URL_PATH + 'autocomplete-town', +            associated_model=models.Town), +        validators=[models.valid_id(models.Town)], label=label, +        help_text=mark_safe(help_text), required=required) +  def get_advanced_town_field(label=_(u"Town"), required=True):      # !FIXME hard_link, reverse_lazy doen't seem to work with formsets      return forms.IntegerField( -         widget=widgets.JQueryTown("/" + settings.URL_PATH + \ -                                   'autocomplete-advanced-town'), -         validators=[models.valid_id(models.Town)], label=label, -         required=required) +        widget=widgets.JQueryTown( +            "/" + settings.URL_PATH + 'autocomplete-advanced-town'), +        validators=[models.valid_id(models.Town)], label=label, +        required=required) +  def get_person_field(label=_(u"Person"), required=True, person_types=[]):      # !FIXME hard_link, reverse_lazy doen't seem to work with formsets @@ -69,12 +70,13 @@ def get_person_field(label=_(u"Person"), required=True, person_types=[]):      if person_types:          person_types = [              unicode(models.PersonType.objects.get(txt_idx=person_type).pk) -                       for person_type in person_types] +            for person_type in person_types]          url += u"/" + u'_'.join(person_types)      widget = widgets.JQueryAutoComplete(url, associated_model=models.Person)      return forms.IntegerField(widget=widget, label=label, required=required,                                validators=[models.valid_id(models.Person)]) +  class NewItemForm(forms.Form):      def __init__(self, *args, **kwargs):          self.limits = {} @@ -97,6 +99,7 @@ class NewItemForm(forms.Form):                  if len(new_choices) == 1:                      self.fields[key].initial = [new_choices[0][0]] +  class NewImportForm(forms.ModelForm):      class Meta:          model = models.Import @@ -106,12 +109,13 @@ class NewImportForm(forms.ModelForm):          self.instance.user = user          return super(NewImportForm, self).save(commit) +  class TargetKeyForm(forms.ModelForm):      class Meta:          model = models.TargetKey          fields = ('target', 'key', 'value')          widgets = { -            'key': forms.TextInput(attrs={'readonly':'readonly'}), +            'key': forms.TextInput(attrs={'readonly': 'readonly'}),              'value': forms.Select(),          } @@ -121,7 +125,8 @@ class TargetKeyForm(forms.ModelForm):          if instance and instance.pk:              self.fields['target'].widget.attrs['readonly'] = True              self.fields['key'].widget.attrs['readonly'] = True -        self.fields['value'].widget.choices = list(instance.target.get_choices()) +        self.fields['value'].widget.choices = list( +            instance.target.get_choices())          self.fields['key'].required = False          self.fields['value'].required = False @@ -146,11 +151,12 @@ class TargetKeyForm(forms.ModelForm):              self.associated_import = None              self.instance.save() +  class OrganizationForm(NewItemForm):      form_label = _(u"Organization") -    associated_models = {'organization_type':models.OrganizationType} -    name = forms.CharField(label=_(u"Name"), max_length=300, -                              validators=[name_validator]) +    associated_models = {'organization_type': models.OrganizationType} +    name = forms.CharField( +        label=_(u"Name"), max_length=300, validators=[name_validator])      organization_type = forms.ChoiceField(label=_(u"Organization type"),                                            choices=[])      address = forms.CharField(label=_(u"Address"), widget=forms.Textarea, @@ -170,20 +176,21 @@ class OrganizationForm(NewItemForm):      def __init__(self, *args, **kwargs):          super(OrganizationForm, self).__init__(*args, **kwargs)          self.fields['organization_type'].choices = \ -                                          models.OrganizationType.get_types() +            models.OrganizationType.get_types()          self.fields['organization_type'].help_text = \ -                                          models.OrganizationType.get_help() +            models.OrganizationType.get_help()          self.limit_fields()      def save(self, user):          dct = self.cleaned_data          dct['history_modifier'] = user          dct['organization_type'] = models.OrganizationType.objects.get( -                                                    pk=dct['organization_type']) +            pk=dct['organization_type'])          new_item = models.Organization(**dct)          new_item.save()          return new_item +  class OrganizationSelect(TableSelect):      name = forms.CharField(label=_(u"Name"), max_length=300)      organization_type = forms.ChoiceField(label=_(u"Type"), choices=[]) @@ -191,56 +198,65 @@ class OrganizationSelect(TableSelect):      def __init__(self, *args, **kwargs):          super(OrganizationSelect, self).__init__(*args, **kwargs)          self.fields['organization_type'].choices = \ -                                models.OrganizationType.get_types() +            models.OrganizationType.get_types() +  class OrganizationFormSelection(forms.Form):      form_label = _(u"Organization search") -    associated_models = {'pk':models.Organization} -    currents = {'pk':models.Organization} -    pk = forms.IntegerField(label="", -         widget=widgets.JQueryJqGrid(reverse_lazy('get-organization'), -                                     OrganizationSelect, models.Organization), -         validators=[models.valid_id(models.Organization)]) +    associated_models = {'pk': models.Organization} +    currents = {'pk': models.Organization} +    pk = forms.IntegerField( +        label="", +        widget=widgets.JQueryJqGrid(reverse_lazy('get-organization'), +                                    OrganizationSelect, models.Organization), +        validators=[models.valid_id(models.Organization)]) +  class BaseOrganizationForm(forms.ModelForm):      form_prefix = "orga" +      class Meta:          model = models.Organization          fields = ['name', 'organization_type', 'address', 'address_complement', -                  'town', 'postal_code',] +                  'town', 'postal_code'] +  class PersonSelect(TableSelect):      name = forms.CharField(label=_(u"Name"), max_length=30)      surname = forms.CharField(label=_(u"Surname"), max_length=20)      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)]) +    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(PersonSelect, self).__init__(*args, **kwargs)          self.fields['person_types'].choices = models.PersonType.get_types() +  class PersonFormSelection(forms.Form):      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'), -                                     PersonSelect, models.Person), -         validators=[models.valid_id(models.Person)]) +    associated_models = {'pk': models.Person} +    currents = {'pk': models.Person} +    pk = forms.IntegerField( +        label="", +        widget=widgets.JQueryJqGrid(reverse_lazy('get-person'), +                                    PersonSelect, models.Person), +        validators=[models.valid_id(models.Person)]) +  class SimplePersonForm(NewItemForm):      form_label = _("Identity") -    associated_models = {'attached_to':models.Organization} +    associated_models = {'attached_to': models.Organization}      title = forms.ChoiceField(label=_("Title"), choices=models.Person.TYPE)      surname = forms.CharField(label=_(u"Surname"), max_length=20,                                validators=[name_validator])      name = forms.CharField(label=_(u"Name"), max_length=30, -                              validators=[name_validator]) +                           validators=[name_validator])      address = forms.CharField(label=_(u"Address"), widget=forms.Textarea,                                required=False)      address_complement = forms.CharField(label=_(u"Address complement"), @@ -254,28 +270,31 @@ class SimplePersonForm(NewItemForm):      phone = forms.CharField(label=_(u"Phone"), max_length=18, required=False)      mobile_phone = forms.CharField(label=_(u"Town"), max_length=18,                                     required=False) -    attached_to = forms.IntegerField(label=_("Current organization"), +    attached_to = forms.IntegerField( +        label=_("Current organization"),          widget=widgets.JQueryAutoComplete( -                    reverse_lazy('autocomplete-organization'), -                    associated_model=models.Organization, new=True), +            reverse_lazy('autocomplete-organization'), +            associated_model=models.Organization, new=True),          validators=[models.valid_id(models.Organization)], required=False) +  class BasePersonForm(forms.ModelForm):      class Meta:          model = models.Person          fields = ['title', 'name', 'surname', 'address', 'address_complement',                    'town', 'postal_code'] +  class BaseOrganizationPersonForm(forms.ModelForm):      class Meta:          model = models.Person -        fields = ['attached_to', 'title', 'name', 'surname',] -        widgets = {'attached_to':widgets.JQueryPersonOrganization( -                reverse_lazy('autocomplete-organization'), -                reverse_lazy('organization_create'), -                model=models.Organization, -                attrs={'hidden':True}, -                new=True), +        fields = ['attached_to', 'title', 'name', 'surname'] +        widgets = {'attached_to': widgets.JQueryPersonOrganization( +            reverse_lazy('autocomplete-organization'), +            reverse_lazy('organization_create'), +            model=models.Organization, +            attrs={'hidden': True}, +            new=True),          }      def __init__(self, *args, **kwargs): @@ -293,14 +312,16 @@ class BaseOrganizationPersonForm(forms.ModelForm):                  person.save()          return person +  class PersonForm(SimplePersonForm): -    person_types = forms.MultipleChoiceField(label=_("Person type"), -                             choices=[], widget=forms.CheckboxSelectMultiple) +    person_types = forms.MultipleChoiceField( +        label=_("Person type"), choices=[], +        widget=forms.CheckboxSelectMultiple)      def __init__(self, *args, **kwargs):          super(PersonForm, self).__init__(*args, **kwargs)          self.fields['person_types'].choices = models.PersonType.get_types( -                                                         empty_first=False) +            empty_first=False)          self.fields['person_types'].help_text = models.PersonType.get_help()          self.limit_fields() @@ -309,48 +330,58 @@ class PersonForm(SimplePersonForm):          dct['history_modifier'] = user          if 'attached_to' in dct and dct['attached_to']:              dct['attached_to'] = models.Organization.objects.get( -                                                     pk=dct['attached_to']) +                pk=dct['attached_to'])          person_types = dct.pop('person_types')          new_item = models.Person.objects.create(**dct)          for pt in person_types:              new_item.person_types.add(pt)          return new_item + +class NoOrgaPersonForm(PersonForm): +    def __init__(self, *args, **kwargs): +        super(NoOrgaPersonForm, self).__init__(*args, **kwargs) +        self.fields.pop('attached_to') + +  class PersonTypeForm(forms.Form):      form_label = _("Person type")      base_model = 'person_type' -    associated_models = {'person_type':models.PersonType} -    person_type = forms.MultipleChoiceField(label=_("Person type"), -                             choices=[], widget=forms.CheckboxSelectMultiple) +    associated_models = {'person_type': models.PersonType} +    person_type = forms.MultipleChoiceField( +        label=_("Person type"), choices=[], +        widget=forms.CheckboxSelectMultiple)      def __init__(self, *args, **kwargs):          super(PersonTypeForm, self).__init__(*args, **kwargs)          self.fields['person_type'].choices = models.PersonType.get_types( -                                                         empty_first=False) +            empty_first=False)          self.fields['person_type'].help_text = models.PersonType.get_help() +  class AccountForm(forms.Form):      form_label = _("Account") -    associated_models = {'pk':models.Person} -    currents = {'pk':models.Person} -    pk = forms.IntegerField(label=u"", widget=forms.HiddenInput, required=False) +    associated_models = {'pk': models.Person} +    currents = {'pk': models.Person} +    pk = forms.IntegerField(label=u"", widget=forms.HiddenInput, +                            required=False)      username = forms.CharField(label=_(u"Account"), max_length=30)      email = forms.CharField(label=_(u"Email"), max_length=75,                              validators=[validators.validate_email]) -    hidden_password = forms.CharField(label=_(u"New password"), max_length=128, -                                  widget=forms.PasswordInput, required=False, -                                  validators=[validators.MinLengthValidator(4)]) +    hidden_password = forms.CharField( +        label=_(u"New password"), max_length=128, widget=forms.PasswordInput, +        required=False, validators=[validators.MinLengthValidator(4)])      hidden_password_confirm = forms.CharField( -                        label=_(u"New password (confirmation)"), max_length=128, -                        widget=forms.PasswordInput, required=False) +        label=_(u"New password (confirmation)"), max_length=128, +        widget=forms.PasswordInput, required=False)      def __init__(self, *args, **kwargs):          if 'initial' in kwargs and 'pk' in kwargs['initial']:              try:                  person = models.Person.objects.get(pk=kwargs['initial']['pk'])                  account = models.IshtarUser.objects.get(person=person) -                kwargs['initial'].update({'username':account.username, -                                          'email':account.email}) +                kwargs['initial'].update({'username': account.username, +                                          'email': account.email})              except ObjectDoesNotExist:                  pass          return super(AccountForm, self).__init__(*args, **kwargs) @@ -358,23 +389,25 @@ class AccountForm(forms.Form):      def clean(self):          cleaned_data = self.cleaned_data          password = cleaned_data.get("hidden_password") -        if password and password != cleaned_data.get("hidden_password_confirm"): +        if password and \ +                password != cleaned_data.get("hidden_password_confirm"):              raise forms.ValidationError(_(u"Your password and confirmation "                                            u"password do not match."))          if not cleaned_data.get("pk"):              models.is_unique(User, 'username')(cleaned_data.get("username"))              if not password: -                raise forms.ValidationError(_(u"You must provide a correct "\ +                raise forms.ValidationError(_(u"You must provide a correct "                                                u"password."))          # check username unicity -        usernames = models.IshtarUser.objects.filter(username= -                                                  cleaned_data.get('username')) +        usernames = models.IshtarUser.objects.filter( +            username=cleaned_data.get('username'))          if cleaned_data.get('pk'):              usernames.exclude(pk=cleaned_data.get('pk'))          if usernames.count():              raise forms.ValidationError(_(u"This username already exists."))          return cleaned_data +  class FinalAccountForm(forms.Form):      final = True      form_label = _("Confirm") @@ -385,12 +418,14 @@ class FinalAccountForm(forms.Form):          self.is_hidden = True          return super(FinalAccountForm, self).__init__(*args, **kwargs) +  class TownForm(forms.Form):      form_label = _("Towns")      base_model = 'town' -    associated_models = {'town':models.Town} +    associated_models = {'town': models.Town}      town = get_town_field(required=False) +  class TownFormSet(FormSet):      def clean(self):          """Checks that no towns are duplicated.""" @@ -400,9 +435,11 @@ class TownFormSet(FormSet):  TownFormset = formset_factory(TownForm, can_delete=True, formset=TownFormSet)  TownFormset.form_label = _("Towns") +  class MergeFormSet(BaseModelFormSet):      from_key = ''      to_key = '' +      def __init__(self, *args, **kwargs):          self._cached_list = []          super(MergeFormSet, self).__init__(*args, **kwargs) @@ -426,11 +463,11 @@ class MergeFormSet(BaseModelFormSet):          if self.is_bound and i < self.initial_form_count():              # Import goes here instead of module-level because importing              # django.db has side effects. -            from django.db import connections +            #  from django.db import connections              pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)              pk = self.data[pk_key] -            pk_field = self.model._meta.pk -            """pk = pk_field.get_db_prep_lookup('exact', pk, +            """pk_field = self.model._meta.pk +            pk = pk_field.get_db_prep_lookup('exact', pk,                  connection=connections[self.get_queryset().db])"""              pk = self.get_restricted_queryset()[i].pk              if isinstance(pk, list): @@ -441,7 +478,8 @@ class MergeFormSet(BaseModelFormSet):          if i >= self.initial_form_count() and self.initial_extra:              # Set initial values for extra forms              try: -                kwargs['initial'] = self.initial_extra[i-self.initial_form_count()] +                kwargs['initial'] = \ +                    self.initial_extra[i-self.initial_form_count()]              except IndexError:                  pass          return super(BaseModelFormSet, self)._construct_form(i, **kwargs) @@ -464,8 +502,10 @@ class MergeFormSet(BaseModelFormSet):          self._cached_list = res          return res +  class MergeForm(forms.ModelForm): -    id = forms.IntegerField(label=u"", widget=forms.HiddenInput, required=False) +    id = forms.IntegerField( +        label=u"", widget=forms.HiddenInput, required=False)      a_is_duplicate_b = forms.BooleanField(required=False)      b_is_duplicate_a = forms.BooleanField(required=False)      not_duplicate = forms.BooleanField(required=False) @@ -492,13 +532,14 @@ class MergeForm(forms.ModelForm):          else:              return          try: -            reverse = self.instance.__class__.objects.get( -                **{self.TO_KEY:from_item, -                   self.FROM_KEY:to_item}).delete() +            self.instance.__class__.objects.get( +                **{self.TO_KEY: from_item, +                   self.FROM_KEY: to_item}).delete()          except ObjectDoesNotExist:              pass          self.instance.delete() +  class MergePersonForm(MergeForm):      class Meta:          model = models.Person @@ -507,6 +548,7 @@ class MergePersonForm(MergeForm):      FROM_KEY = 'from_person'      TO_KEY = 'to_person' +  class MergeOrganizationForm(MergeForm):      class Meta:          model = models.Organization @@ -521,12 +563,12 @@ class MergeOrganizationForm(MergeForm):  ######################  class SourceForm(forms.Form):      form_label = _(u"Documentation informations") -    associated_models = {'source_type':models.SourceType} +    associated_models = {'source_type': models.SourceType}      title = forms.CharField(label=_(u"Title"),                              validators=[validators.MaxLengthValidator(200)])      source_type = forms.ChoiceField(label=_(u"Source type"), choices=[]) -    associated_url = forms.URLField(required=False, -                                 label=_(u"Numerical ressource (web address)")) +    associated_url = forms.URLField( +        required=False, label=_(u"Numerical ressource (web address)"))      receipt_date = forms.DateField(label=_(u"Receipt date"), required=False,                                     widget=widgets.JQueryDate)      creation_date = forms.DateField(label=_(u"Creation date"), required=False, @@ -536,12 +578,14 @@ class SourceForm(forms.Form):          super(SourceForm, self).__init__(*args, **kwargs)          self.fields['source_type'].choices = models.SourceType.get_types() +  class SourceSelect(TableSelect):      authors = forms.IntegerField( -         widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ -                     'autocomplete-author', associated_model=models.Author), -         validators=[models.valid_id(models.Author)], label=_(u"Author"), -         required=False) +        widget=widgets.JQueryAutoComplete( +            "/" + settings.URL_PATH + 'autocomplete-author', +            associated_model=models.Author), +        validators=[models.valid_id(models.Author)], label=_(u"Author"), +        required=False)      source_type = forms.ChoiceField(label=_("Source type"), choices=[]) @@ -550,6 +594,7 @@ class SourceSelect(TableSelect):          self.fields['source_type'].choices = models.SourceType.get_types()          self.fields['source_type'].help_text = models.SourceType.get_help() +  class SourceDeletionForm(FinalForm):      confirm_msg = " "      confirm_end_msg = _(u"Would you like to delete this documentation?") @@ -558,14 +603,16 @@ class SourceDeletionForm(FinalForm):  # Authors management #  ###################### +  class AuthorForm(NewItemForm):      form_label = _(u"Author") -    associated_models = {'person':models.Person, -                         'author_type':models.AuthorType} +    associated_models = {'person': models.Person, +                         'author_type': models.AuthorType}      person = forms.IntegerField( -         widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ -               'autocomplete-person', associated_model=models.Person, new=True), -         validators=[models.valid_id(models.Person)], label=_(u"Person")) +        widget=widgets.JQueryAutoComplete( +            "/" + settings.URL_PATH + 'autocomplete-person', +            associated_model=models.Person, new=True), +        validators=[models.valid_id(models.Person)], label=_(u"Person"))      author_type = forms.ChoiceField(label=_(u"Author type"), choices=[])      def __init__(self, *args, **kwargs): @@ -576,7 +623,7 @@ class AuthorForm(NewItemForm):      def save(self, user):          dct = self.cleaned_data          dct['author_type'] = models.AuthorType.objects.get( -                                                     pk=dct['author_type']) +            pk=dct['author_type'])          dct['person'] = models.Person.objects.get(pk=dct['person'])          new_item = models.Author(**dct)          new_item.save() @@ -586,11 +633,13 @@ class AuthorForm(NewItemForm):  class AuthorFormSelection(forms.Form):      form_label = _(u"Author selection")      base_model = 'author' -    associated_models = {'author':models.Author} +    associated_models = {'author': models.Author}      author = forms.IntegerField( -         widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ -               'autocomplete-author', associated_model=models.Author, new=True), -         validators=[models.valid_id(models.Author)], label=_(u"Author")) +        widget=widgets.JQueryAutoComplete( +            "/" + settings.URL_PATH + 'autocomplete-author', +            associated_model=models.Author, new=True), +        validators=[models.valid_id(models.Author)], label=_(u"Author")) +  class AuthorFormSet(FormSet):      def clean(self): @@ -601,4 +650,3 @@ class AuthorFormSet(FormSet):  AuthorFormset = formset_factory(AuthorFormSelection, can_delete=True,                                  formset=AuthorFormSet)  AuthorFormset.form_label = _("Authors") -  | 
