docbow: add minimum number of files limitation to FileTypeAttachedFileKind model

fixes #3588
This commit is contained in:
Benjamin Dauvergne 2013-09-11 13:29:05 +02:00
parent c725f50c81
commit a997886429
5 changed files with 332 additions and 122 deletions

View File

@ -200,12 +200,13 @@ class FileForm(RecipientForm, ModelForm):
cleaned_data = super(FileForm, self).clean()
for field, attached_file_kind in self.content_fields:
upload_id, upload_files = self.cleaned_data.get(field, (None, []))
cardinality = attached_file_kind.cardinality
max_files = attached_file_kind.cardinality
min_files = attached_file_kind.minimum
errors = []
if cardinality and len(upload_files) > cardinality:
errors.append(_(u'You must attach at most %d file(s).') % cardinality)
if len(upload_files) == 0:
errors.append(_(u'You must attach at least one file.'))
if max_files and len(upload_files) > max_files:
errors.append(_(u'You must attach at most %d file(s).') % max_files)
if min_files and len(upload_files) < min_files:
errors.append(_(u'You must attach at least %d file(s).') % min_files)
for upload_file in upload_files:
if not attached_file_kind.match_file(upload_file):
mime_types = attached_file_kind.get_mime_types()

View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: docbow 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-09-11 12:29+0200\n"
"PO-Revision-Date: 2013-09-11 12:29+0200\n"
"POT-Creation-Date: 2013-09-11 13:27+0200\n"
"PO-Revision-Date: 2013-09-11 13:27+0200\n"
"Last-Translator: Benjamin Dauvergne <bdauvergne@entrouvert.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -27,11 +27,11 @@ msgstr "Activer les objets sélectionnés"
msgid "De-activate selected objects"
msgstr ""
#: admin.py:40 models.py:691
#: admin.py:40 models.py:696
msgid "Limitation des destinataires"
msgstr ""
#: admin.py:45 models.py:688
#: admin.py:45 models.py:693
msgid "Limitation des types de fichier"
msgstr ""
@ -76,7 +76,7 @@ msgid "Clear failure and done field, resubmitting the notifications."
msgstr ""
"Réinitialise les champs accompli et erreur, et re-soumet la notification."
#: admin.py:224 models.py:178
#: admin.py:224 models.py:183
msgid "Document"
msgstr "Document"
@ -88,7 +88,7 @@ msgstr ""
msgid "None"
msgstr ""
#: admin.py:245 forms.py:332 templates/admin/object_history.html:26
#: admin.py:245 forms.py:333 templates/admin/object_history.html:26
msgid "User"
msgstr "Utilisateur"
@ -142,7 +142,7 @@ msgstr "Contacter un administrateur du système"
msgid "Your delegation does not allow you to do this action"
msgstr "Votre délégation ne vous permet pas d'accomplir cette action"
#: fields.py:69 forms.py:55 forms.py:109 models.py:255
#: fields.py:69 forms.py:55 forms.py:109 models.py:260
msgid "Recipients"
msgstr "Destinataire(s)"
@ -151,7 +151,7 @@ msgid "you must set at least one user recipient or one list recipient..."
msgstr ""
"Vous devez choisir au moins un utilisateur ou une liste destinataire..."
#: forms.py:56 models.py:185
#: forms.py:56 models.py:190
msgid "Sender"
msgstr "Expéditeur"
@ -163,53 +163,54 @@ msgstr "Transférer le document"
msgid "send a file"
msgstr "Envoyer le document"
#: forms.py:164 models.py:216 models.py:234
#: forms.py:164 models.py:221 models.py:239
msgid "Attached files"
msgstr "Fichiers attaché(s)"
#: forms.py:206
#: forms.py:207
#, python-format
msgid "You must attach at most %d file(s)."
msgstr "Vous devez attacher au plus %d fichier(s)."
#: forms.py:208
msgid "You must attach at least one file."
msgstr "Vous devez attacher au moins un fichier."
#: forms.py:209
#, python-format
msgid "You must attach at least %d file(s)."
msgstr "Vous devez attacher au moins %d fichier(s)."
#: forms.py:213
#: forms.py:214
msgid ""
"The file name \"{file_name}\" does not match the patterns \"{extensions}\"."
msgstr ""
#: forms.py:252 forms.py:277
#: forms.py:253 forms.py:278
msgid "send your message"
msgstr "Envoyer le message"
#: forms.py:259
#: forms.py:260
msgid "Subject"
msgstr "Sujet"
#: forms.py:262
#: forms.py:263
msgid "Message"
msgstr "Message"
#: forms.py:284 models.py:481 models.py:570
#: forms.py:285 models.py:486 models.py:575
msgid "Name"
msgstr "Nom"
#: forms.py:285 forms.py:331
#: forms.py:286 forms.py:332
msgid "Email"
msgstr ""
#: forms.py:286
#: forms.py:287
msgid "Phone number"
msgstr "Numéro de téléphone"
#: forms.py:303
#: forms.py:304
msgid "Persons"
msgstr "Personnes"
#: forms.py:317
#: forms.py:318
msgid ""
"<p>You can delegate to a newly created user, then all following fields are "
"mandatory:</p>"
@ -217,24 +218,24 @@ msgstr ""
"<p>Vous pouvez déléguer à un nouvel utilisateur que vous créez — tous les "
"champs suivants sont obligatoires dans ce cas:</p>"
#: forms.py:319
#: forms.py:320
msgid "<p>or you can delegate to an existing user:</p>"
msgstr "<p>ou bien déléguer à un utilisateur existant:</p>"
#: forms.py:322 templates/docbow/delegate.html:57
#: forms.py:323 templates/docbow/delegate.html:57
#: templates/docbow/full-profile.html:69
msgid "Create a new delegation"
msgstr "Créer une nouvelle délégation"
#: forms.py:329
#: forms.py:330
msgid "Firstname"
msgstr "Prénom"
#: forms.py:330
#: forms.py:331
msgid "Lastname"
msgstr "Nom"
#: forms.py:354
#: forms.py:355
msgid ""
"You must choose between creating a new user or delegating to an existing "
"one; the two are mutually exclusive."
@ -242,7 +243,7 @@ msgstr ""
"Vous devez choisir entre déléguer à un nouvel utilisateur qui sera créé ou "
"déléguer à un utilisateur existant, les deux choix s'excluant mutuellement."
#: forms.py:358
#: forms.py:359
msgid ""
"To create a new user you must give a first name, a last name and a valid "
"email"
@ -250,13 +251,13 @@ msgstr ""
"Pour créer un nouvel utilisateur vous devez donner un prénom, un nom et une "
"adresse de courriel valide."
#: forms.py:375
#: forms.py:376
msgid "A forwarding rule must have at least one recipient, person or list."
msgstr ""
"Une règle de transfert doit contenir au moins un nouveau destinataire; une "
"personne ou une liste."
#: forms.py:392
#: forms.py:393
msgid ""
"<p class=\"formHint\">If You would like to receive a SMS alert each time "
"your inbox receives a document, provide your mobile phone number. If you do "
@ -267,15 +268,15 @@ msgstr ""
"de téléphone. Si vous ne remplissez pas ce champ, vous ne recevrez pas de "
"SMS.</p>"
#: forms.py:398
#: forms.py:399
msgid "Clear SMS alert"
msgstr "Supprimer l'alerte par SMS"
#: forms.py:399
#: forms.py:400
msgid "Validate"
msgstr "Valider"
#: forms.py:406
#: forms.py:407
msgid ""
"Use international phone number format, i.e +[country code][number]. A "
"challenge SMS will be sent to you to validate it."
@ -285,15 +286,15 @@ msgstr ""
"code vous sera envoyé et il vous faudra valider une deuxième fois votre "
"numéro avec le code."
#: forms.py:432
#: forms.py:433
msgid "Enter code received by SMS"
msgstr "Entrez le code reçu par SMS"
#: forms.py:453
#: forms.py:454
msgid "E-mail or identifier"
msgstr "E-mail ou nom d'utilisateur"
#: forms.py:469
#: forms.py:470
msgid ""
"That e-mail address or identifier doesn't have an associated user account. "
"Are you sure you've registered?"
@ -301,15 +302,15 @@ msgstr ""
"Cette adresse email ou cet identifiant n'ont pas de compte utilisateur "
"associé.Êtes-vous bien sûr d'être enregistré?"
#: forms.py:487
#: forms.py:488
msgid "From"
msgstr "De"
#: forms.py:488 templates/docbow/message.html:34
#: forms.py:489 templates/docbow/message.html:34
msgid "To"
msgstr "Destinataire(s)"
#: forms.py:503
#: forms.py:504
msgid "From must be inferior or equal to To"
msgstr "Le début de la période doit être inférieur ou égal à sa fin"
@ -325,7 +326,7 @@ msgstr "Plate-forme sécurisée d'échange de documents"
msgid "Docbow_app"
msgstr "Plate-forme sécurisée d'échange de documents"
#: models.py:59 models.py:576
#: models.py:59 models.py:581
msgid "is active"
msgstr "Activé"
@ -354,104 +355,119 @@ msgid "cardinality"
msgstr "nombre de fichiers maximum"
#: models.py:89
msgid "zero is a special value setting no limitation"
msgstr "zéro est une valeur spéciale qui signifie \"sans limitation\""
#: models.py:91
msgid "minimum number of files"
msgstr "nombre de fichiers minimum"
#: models.py:92
msgid "position"
msgstr ""
#: models.py:94
#: models.py:96
msgid ""
"minimum must be inferior to maximum number of files if maximum is not zero"
msgstr ""
"le minimum doit être inférieur au maximum du nombre de fichiers si le "
"maximum n'est pas nul"
#: models.py:99
msgid "invalid mime types list"
msgstr "liste de types MIME invalide"
#: models.py:111
#: models.py:116
msgid "file type attached file kind"
msgstr "Type de fichiers attachés pour un type de document"
#: models.py:112
#: models.py:117
msgid "file type attached file kinds"
msgstr "Types de fichiers attachés pour un type de document"
#: models.py:126
#: models.py:131
msgid "Content"
msgstr "Description des contenus"
#: models.py:127
#: models.py:132
msgid "Contents"
msgstr "Descriptions des contenus"
#: models.py:179 templates/docbow/mailbox_list.html:18
#: models.py:184 templates/docbow/mailbox_list.html:18
msgid "Documents"
msgstr "Documents"
#: models.py:181
#: models.py:186
msgid "Can forward documents"
msgstr "Peut transférer des documents"
#: models.py:187
#: models.py:192
msgid "Real sender"
msgstr "Expéditeur réel"
#: models.py:189
#: models.py:194
msgid "Date d'envoi"
msgstr ""
#: models.py:191
#: models.py:196
msgid "Users to send to"
msgstr "Aux utilisateurs"
#: models.py:193
#: models.py:198
msgid "Groups to send to"
msgstr "Aux listes des"
#: models.py:194
#: models.py:199
msgid "Document type"
msgstr "Type de document"
#: models.py:196
#: models.py:201
msgid "Comments"
msgstr "Description du contenu"
#: models.py:198
#: models.py:203
msgid "Reply to"
msgstr "Réponse à"
#: models.py:210
#: models.py:215
msgid ""
"document {id} sent on {date} of type {filetype} about {comment} by {sender}"
msgstr ""
"document {id} envoyé le {date} du type {filetype} à propos de {comment} par "
"{sender}"
#: models.py:402
#: models.py:407
msgid ""
"forwarded document {from_document} as {to_document} on {date} automatically"
msgstr ""
"document {from_document} transféré en {to_document} le {date} automatiquement"
#: models.py:407
#: models.py:412
msgid "forwarded document {from_document} as {to_document} on {date}"
msgstr "document {from_document} transféré en {to_document} le {date}"
#: models.py:430
#: models.py:435
msgid "filetype"
msgstr "Type de fichier"
#: models.py:433
#: models.py:438
msgid "Original recipients"
msgstr "Destinataires d'origine"
#: models.py:434
#: models.py:439
msgid "At least one recipient must match for the rule to apply."
msgstr ""
"Au moins un destinataire doit correspondre pour que la règle s'applique."
#: models.py:437
#: models.py:442
msgid "Users to forward to"
msgstr "Aux utilisateurs"
#: models.py:439
#: models.py:444
msgid "Groups to forward to"
msgstr "Aux listes des"
#: models.py:450
#: models.py:455
msgid ""
"Forward documents of type {filetypes} and to {originaly_to_user} "
"automatically to {to}"
@ -459,95 +475,95 @@ msgstr ""
"Transfert les documents du type {filetypes} et à destination de "
"{originaly_to_user} automatiquement à {to}"
#: models.py:452
#: models.py:457
msgid "Forward documents of type {filetypes} automatically to {to}"
msgstr "Transfert les documents du type {filetypes} automatiquement à {to}"
#: models.py:454
#: models.py:459
msgid "Forward documents to {originaly_to_user} automatically to {to}"
msgstr ""
"Transfert les documents à destination de {originaly_to_user} automatiquement "
"à {to}"
#: models.py:475
#: models.py:480
msgid "Automatic forwarding rule"
msgstr "Règle de transfert automatique"
#: models.py:476
#: models.py:481
msgid "Automatic forwarding rules"
msgstr "Règles de transfert automatique"
#: models.py:482
#: models.py:487
msgid "File"
msgstr "Fichier"
#: models.py:483
#: models.py:488
msgid "Attached to"
msgstr "Attaché à"
#: models.py:486
#: models.py:491
msgid "attached file kind"
msgstr "Type de fichiers attachés pour un type de document"
#: models.py:526
#: models.py:531
msgid "Account delegation"
msgstr "Délégation de compte"
#: models.py:527
#: models.py:532
msgid "Account delegations"
msgstr "Délégations de compte"
#: models.py:531
#: models.py:536
msgctxt "delegation from"
msgid "From"
msgstr "Par"
#: models.py:533
#: models.py:538
msgctxt "delegation to"
msgid "To"
msgstr "À"
#: models.py:568
#: models.py:573
msgid "Mailing list"
msgstr "Liste de destinataires"
#: models.py:569
#: models.py:574
msgid "Mailing lists"
msgstr "Listes de destinataires"
#: models.py:571
#: models.py:576
msgid "Members"
msgstr "Membres"
#: models.py:574
#: models.py:579
msgid "Mailing lists members"
msgstr "Listes membres"
#: models.py:618
#: models.py:623
msgid "Mailbox owner"
msgstr "Propriétaire de la boite de courrier"
#: models.py:622
#: models.py:627
msgid "Seen"
msgstr "Vu"
#: models.py:623
#: models.py:628
msgid "Deleted"
msgstr "Effacé"
#: models.py:624
#: models.py:629
msgid "Outbox message"
msgstr "Boite d'émission"
#: models.py:630
#: models.py:635
msgid "Mailbox"
msgstr "Boite de réception"
#: models.py:631
#: models.py:636
msgid "Mailboxes"
msgstr "Boites de réception"
#: models.py:635
#: models.py:640
msgid ""
"seen and deleted mailbox entry {id} of user {user}:{user.id} created on "
"{date} for {document}"
@ -555,7 +571,7 @@ msgstr ""
"entrée {id} de la boite au lettre de l'utilisateur {user}:{user.id} créée le "
"{date} pour le document {document} puis lue et supprimée"
#: models.py:640
#: models.py:645
msgid ""
"deleted mailbox entry {id} of user {user}:{user.id} created on {date} for "
"{document}"
@ -563,7 +579,7 @@ msgstr ""
"entrée {id} de la boite au lettre de l'utilisateur {user}:{user.id} créée le "
"{date} pour le document {document} puis jamais lue et supprimée"
#: models.py:645
#: models.py:650
msgid ""
"seen mailbox entry {id} of user {user}:{user.id} created on {date} for "
"{document}"
@ -571,42 +587,42 @@ msgstr ""
"entrée {id} de la boite au lettre de l'utilisateur {user}:{user.id} créée le "
"{date} pour le document {document} puis jamais lue"
#: models.py:650
#: models.py:655
msgid ""
"mailbox entry {id} of user {user}:{user.id} created on {date} for {document}"
msgstr ""
"entrée {id} de la boite au lettre de l'utilisateur {user}:{user.id} créée le "
"{date} pour le document {document}"
#: models.py:657
#: models.py:662
msgid "Docbow admin user"
msgstr "Utilisateur"
#: models.py:664
#: models.py:669
msgid "Docbow admin group"
msgstr "Profil"
#: models.py:672
#: models.py:677
msgid "Inbox"
msgstr "Message(s) reçu(s)"
#: models.py:673
#: models.py:678
msgid "Inboxes"
msgstr "Message(s) reçu(s)"
#: models.py:679
#: models.py:684
msgid "Outbox"
msgstr "Message(s) émi(s)"
#: models.py:680
#: models.py:685
msgid "Outboxes"
msgstr "Message(s) émi(s)"
#: models.py:694 models.py:695
#: models.py:699 models.py:700
msgid "Limitation par liste de destinataires"
msgstr ""
#: models.py:699
#: models.py:704
msgid ""
"sending limitation for list {mailing_list} to filetypes{filetypes} and lists "
"{lists}"
@ -614,19 +630,19 @@ msgstr ""
"limitation d'envoi pour la liste {mailing_list} restreinte auxtypes de "
"fichier {filetypes} et aux listes {lists}"
#: models.py:709
#: models.py:714
msgid "Guest user"
msgstr "Utilisateur invité"
#: models.py:710
#: models.py:715
msgid "Mobile phone"
msgstr "Téléphone mobile"
#: models.py:712
#: models.py:717
msgid "personal email address"
msgstr "Adresse email personnelle"
#: models.py:713
#: models.py:718
msgid ""
"if you provide a personal email address, notifications of new documents will "
"also be sent to this address."
@ -635,13 +651,13 @@ msgstr ""
"adresse pour chaque nouveau document qui vous est adressé sur la plate-forme "
"(identique au mail que vous recevez sur votre adresse institutionnelle)."
#: models.py:717
#: models.py:722
msgid ""
"docbow profile of {user}:{user.id} with mobile phone {mobile_phone} and "
"personal email {personal_email}"
msgstr ""
#: models.py:755
#: models.py:760
msgid "notification {0}:{1}"
msgstr ""
@ -726,7 +742,7 @@ msgstr "nom de fichier trop long, seulement %d caractères sont permis"
msgid "too much file attached, delete to add a new one"
msgstr "trop de fichiers attachés, supprimez en un pour en ajouter un autre"
#: views.py:172
#: views.py:171
msgid ""
"An internal error occured, administrators have been notified; sending seems "
"blocked at the moment. You should try agrain later. If it still does not "
@ -737,26 +753,26 @@ msgstr ""
"incitons à réessayer plus tard. Si cela ne fonctionne toujours pas, prenez "
"contact avec les gestionnaires."
#: views.py:233
#: views.py:232
msgid "back to inbox"
msgstr "Retour aux documents reçus"
#: views.py:235
#: views.py:234
msgid "back to outbox"
msgstr "Retour aux documents envoyés"
#: views.py:249
#: views.py:248
msgid "Document forwarded to {recipients_count} recipient."
msgid_plural "Document forwarded to {recipients_count} recipients."
msgstr[0] "Document tranféré à {recipients_count} destinataire."
msgstr[1] "Document tranféré à {recipients_count} destinataires."
#: views.py:319 views.py:323
#: views.py:318 views.py:322
#, python-format
msgid "Message from %(name)s <%(email)s>"
msgstr "Message de %(name)s <%(email)s>"
#: views.py:325
#: views.py:324
#, python-format
msgid ""
"\n"
@ -765,17 +781,17 @@ msgstr ""
"\n"
"Numéro de téléphone: %s"
#: views.py:330
#: views.py:329
#, python-format
msgid "Your message was sent to %d administrators"
msgstr "Votre message a été envoyé à %d administrateurs."
#: views.py:365
#: views.py:364
#, python-format
msgid "back to %s"
msgstr "Retour à %s"
#: views.py:443
#: views.py:442
msgid "Email with password reset instruction has been sent."
msgstr ""
"Un email avec les instructions pour la réinitialisation de votre mot de "
@ -955,10 +971,15 @@ msgstr "Ajouter des fichiers"
msgid "Any type"
msgstr "Tout type de fichier permis"
#: templates/docbow/upload.html:6
#: templates/docbow/upload.html:7
#, python-format
msgid ", maximum %(cardinality)s files"
msgstr ", maximum %(cardinality)s fichiers"
msgid ", maximum %(cardinality)s file(s)"
msgstr ", maximum %(cardinality)s fichier(s)"
#: templates/docbow/upload.html:10
#, python-format
msgid ", minimum %(minimum)s file(s)"
msgstr ", mnimum %(minimum)s fichier(s)"
#: templates/registration/login.html:6
#: templates/registration/password_reset_complete.html:14
@ -1046,6 +1067,9 @@ msgstr "aux %s"
msgid "%(one)s and to lists %(two)s"
msgstr "%(one)s ainsi qu'%(two)s"
#~ msgid "You must attach at least one file."
#~ msgstr "Vous devez attacher au moins un fichier."
#~ msgid "password_change_menu"
#~ msgstr "Changement du mot de passe"

View File

@ -0,0 +1,175 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'FileTypeAttachedFileKind.minimum'
db.add_column('docbow_filetypeattachedfilekind', 'minimum',
self.gf('django.db.models.fields.PositiveSmallIntegerField')(default=0),
keep_default=False)
def backwards(self, orm):
# Deleting field 'FileTypeAttachedFileKind.minimum'
db.delete_column('docbow_filetypeattachedfilekind', 'minimum')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'docbow.attachedfile': {
'Meta': {'object_name': 'AttachedFile'},
'content': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attached_files'", 'to': "orm['docbow.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'kind': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['docbow.FileTypeAttachedFileKind']", 'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'docbow.automaticforwarding': {
'Meta': {'object_name': 'AutomaticForwarding'},
'filetypes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'forwarding_rules'", 'symmetrical': 'False', 'to': "orm['docbow.FileType']"}),
'forward_to_list': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['docbow.MailingList']"}),
'forward_to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'originaly_to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'as_original_recipient_forwarding_rules'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"})
},
'docbow.content': {
'Meta': {'ordering': "['description']", 'object_name': 'Content'},
'description': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'docbow.delegation': {
'Meta': {'ordering': "['by']", 'unique_together': "(('by', 'to'),)", 'object_name': 'Delegation', 'db_table': "'auth_delegation'"},
'by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'delegations_to'", 'to': "orm['auth.User']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'to': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'delegations_by'", 'to': "orm['auth.User']"})
},
'docbow.deletedmailbox': {
'Meta': {'object_name': 'DeletedMailbox'},
'delegate': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['docbow.Mailbox']"})
},
'docbow.docbowprofile': {
'Meta': {'object_name': 'DocbowProfile'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_guest': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
'personal_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'docbow.document': {
'Meta': {'ordering': "['-date']", 'object_name': 'Document'},
'_timestamp': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'filetype': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['docbow.FileType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'real_sender': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['docbow.Document']"}),
'sender': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents_sent'", 'to': "orm['auth.User']"}),
'to_list': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['docbow.MailingList']", 'null': 'True', 'blank': 'True'}),
'to_user': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'directly_received_documents'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"})
},
'docbow.documentforwarded': {
'Meta': {'object_name': 'DocumentForwarded'},
'automatic': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'from_document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'document_forwarded_to'", 'to': "orm['docbow.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'to_document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'document_forwarded_from'", 'to': "orm['docbow.Document']"})
},
'docbow.filetype': {
'Meta': {'ordering': "['name']", 'object_name': 'FileType'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
},
'docbow.filetypeattachedfilekind': {
'Meta': {'ordering': "('file_type', 'position', 'name')", 'unique_together': "(('name', 'file_type'),)", 'object_name': 'FileTypeAttachedFileKind'},
'cardinality': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
'file_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['docbow.FileType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mime_types': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'minimum': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {})
},
'docbow.mailbox': {
'Meta': {'ordering': "['-date']", 'object_name': 'Mailbox'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mailboxes'", 'to': "orm['docbow.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'outbox': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': "orm['auth.User']"}),
'seen': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'docbow.mailinglist': {
'Meta': {'ordering': "['name']", 'object_name': 'MailingList'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'mailing_list_members': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'members_lists'", 'blank': 'True', 'to': "orm['docbow.MailingList']"}),
'members': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'mailing_lists'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'docbow.notification': {
'Meta': {'ordering': "('-id',)", 'object_name': 'Notification'},
'create_dt': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'ctx': ('picklefield.fields.PickledObjectField', [], {'null': 'True', 'blank': 'True'}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['docbow.Document']", 'null': 'True', 'blank': 'True'}),
'done': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'failure': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'kind': ('django.db.models.fields.CharField', [], {'default': "'new-document'", 'max_length': '32'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
'docbow.sendinglimitation': {
'Meta': {'object_name': 'SendingLimitation'},
'filetypes': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'filetype_limitation'", 'blank': 'True', 'to': "orm['docbow.FileType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lists': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'lists_limitation'", 'symmetrical': 'False', 'to': "orm['docbow.MailingList']"}),
'mailing_list': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['docbow.MailingList']", 'unique': 'True'})
}
}
complete_apps = ['docbow']

View File

@ -85,10 +85,15 @@ class FileTypeAttachedFileKind(Model):
help_text=('mime types separated by spaces, wildcards are allowed'),
blank=True)
cardinality = PositiveSmallIntegerField(default=0,
verbose_name=_('cardinality'))
verbose_name=_('cardinality'),
help_text=_('zero is a special value setting no limitation'))
minimum = PositiveSmallIntegerField(default=0,
verbose_name=_('minimum number of files'))
position = PositiveSmallIntegerField(verbose_name=_('position'))
def clean(self):
if self.cardinality != 0 and not self.minimum <= self.cardinality:
raise ValidationError(_('minimum must be inferior to maximum number of files if maximum is not zero'))
if self.mime_types:
if not self.MIME_TYPES_RE.match(self.mime_types):
raise ValidationError(_('invalid mime types list'))

View File

@ -3,8 +3,13 @@
<div class="fileupload-buttonbar">
<label class="fileinput-button">
<span>{% trans "Add File" %} ({% if extensions %}{{ extensions|join:", " }}{% else %}{% trans "Any type" %}{% endif %}
{% if attached_file_kind.cardinality %}{% blocktrans with cardinality=attached_file_kind.cardinality %}, maximum {{ cardinality }} files{% endblocktrans %}{% endif %})</span>
<input type="file" name="{{ name }}" multiple>
{% if attached_file_kind.cardinality %}
{% blocktrans with cardinality=attached_file_kind.cardinality %}, maximum {{ cardinality }} file(s){% endblocktrans %}
{% endif %}
{% if attached_file_kind.cardinality %}
{% blocktrans with minimum=attached_file_kind.minimum %}, minimum {{ minimum }} file(s){% endblocktrans %}
{% endif %})</span>
<input type="file" name="{{ name }}" multiple>
</label>
</div>
<div class="fileupload-content">