diff options
author | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-04-07 02:01:56 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-04-07 02:01:56 +0200 |
commit | 177517832e1e67a97c44cc0a7d79cb79f5e77e03 (patch) | |
tree | 9d0474ef51da9b898b6288ba3d34fb7ed1088cb1 | |
parent | 73eb6055d36fd785c468ed0866df43fd4c3fef44 (diff) | |
download | Chimère-177517832e1e67a97c44cc0a7d79cb79f5e77e03.tar.bz2 Chimère-177517832e1e67a97c44cc0a7d79cb79f5e77e03.zip |
Fixes model type and form validation in edition panel.
* check URL format for multimedia items (closes #333)
* file field is required for pictures (closes #332)
* multimedia type is required for multimedia items (closes #331)
* name is required for pictures and multimedia items (closes #330)
* errors messages are now more visible (closes #328)
-rw-r--r-- | chimere/migrations/0012_auto__chg_field_picturefile_name__chg_field_multimediafile_url__chg_fi.py | 201 | ||||
-rw-r--r-- | chimere/models.py | 6 | ||||
-rw-r--r-- | chimere/static/chimere/css/styles.css | 18 | ||||
-rw-r--r-- | chimere/templates/chimere/blocks/inline_formset.html | 17 | ||||
-rw-r--r-- | chimere/templates/chimere/edit.html | 7 | ||||
-rw-r--r-- | chimere/views.py | 9 |
6 files changed, 240 insertions, 18 deletions
diff --git a/chimere/migrations/0012_auto__chg_field_picturefile_name__chg_field_multimediafile_url__chg_fi.py b/chimere/migrations/0012_auto__chg_field_picturefile_name__chg_field_multimediafile_url__chg_fi.py new file mode 100644 index 0000000..405009a --- /dev/null +++ b/chimere/migrations/0012_auto__chg_field_picturefile_name__chg_field_multimediafile_url__chg_fi.py @@ -0,0 +1,201 @@ +# encoding: 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): + + # Changing field 'PictureFile.name' + db.alter_column('chimere_picturefile', 'name', self.gf('django.db.models.fields.CharField')(default='Default name', max_length=150)) + + # Changing field 'MultimediaFile.url' + db.alter_column('chimere_multimediafile', 'url', self.gf('django.db.models.fields.URLField')(max_length=200)) + + # Changing field 'MultimediaFile.name' + db.alter_column('chimere_multimediafile', 'name', self.gf('django.db.models.fields.CharField')(default='Default name', max_length=150)) + + + def backwards(self, orm): + + # Changing field 'PictureFile.name' + db.alter_column('chimere_picturefile', 'name', self.gf('django.db.models.fields.CharField')(max_length=150, null=True)) + + # Changing field 'MultimediaFile.url' + db.alter_column('chimere_multimediafile', 'url', self.gf('django.db.models.fields.CharField')(max_length=200)) + + # Changing field 'MultimediaFile.name' + db.alter_column('chimere_multimediafile', 'name', self.gf('django.db.models.fields.CharField')(max_length=150, null=True)) + + + models = { + 'chimere.area': { + 'Meta': {'ordering': "('order', 'name')", 'object_name': 'Area'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'lower_right_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'upper_left_corner': ('django.contrib.gis.db.models.fields.PointField', [], {'default': "'POINT(0 0)'"}), + 'urn': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'unique': 'True', 'max_length': '50', 'blank': 'True'}) + }, + 'chimere.category': { + 'Meta': {'ordering': "['order']", 'object_name': 'Category'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.color': { + 'Meta': {'ordering': "['order']", 'object_name': 'Color'}, + 'code': ('django.db.models.fields.CharField', [], {'max_length': '6'}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.colortheme': { + 'Meta': {'object_name': 'ColorTheme'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.icon': { + 'Meta': {'object_name': 'Icon'}, + 'height': ('django.db.models.fields.IntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'width': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.importer': { + 'Meta': {'object_name': 'Importer'}, + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'filtr': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer_type': ('django.db.models.fields.CharField', [], {'max_length': '4'}), + 'source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.marker': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Marker'}, + 'available_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'multimedia_files': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'marker'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['chimere.MultimediaFile']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'pictures': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'marker'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['chimere.PictureFile']"}), + 'point': ('chimere.widgets.PointField', [], {}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_marker'", 'null': 'True', 'to': "orm['chimere.Marker']"}), + 'route': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'associated_marker'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.multimediafile': { + 'Meta': {'object_name': 'MultimediaFile'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multimedia_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.MultimediaType']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'chimere.multimediatype': { + 'Meta': {'object_name': 'MultimediaType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iframe': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'media_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.news': { + 'Meta': {'object_name': 'News'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'content': ('django.db.models.fields.TextField', [], {}), + 'date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'chimere.picturefile': { + 'Meta': {'object_name': 'PictureFile'}, + 'height': ('django.db.models.fields.IntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'miniature': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'width': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.property': { + 'Meta': {'object_name': 'Property'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marker': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Marker']"}), + 'propertymodel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.PropertyModel']"}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'chimere.propertymodel': { + 'Meta': {'ordering': "('order',)", 'object_name': 'PropertyModel'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '1'}) + }, + 'chimere.route': { + 'Meta': {'ordering': "('status', 'name')", 'object_name': 'Route'}, + 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.RouteFile']", 'null': 'True', 'blank': 'True'}), + 'categories': ('chimere.widgets.SelectMultipleField', [], {'to': "orm['chimere.SubCategory']", 'symmetrical': 'False'}), + 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_source': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'import_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'ref_item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'submited_route'", 'null': 'True', 'to': "orm['chimere.Route']"}), + 'route': ('chimere.widgets.RouteField', [], {}), + 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'submiter_comment': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'submiter_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'submiter_session_key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'chimere.routefile': { + 'Meta': {'ordering': "('name',)", 'object_name': 'RouteFile'}, + 'file_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'raw_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'simplified_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}) + }, + 'chimere.subcategory': { + 'Meta': {'ordering': "['category', 'order']", 'object_name': 'SubCategory'}, + 'areas': ('chimere.widgets.SelectMultipleField', [], {'symmetrical': 'False', 'related_name': "'areas'", 'blank': 'True', 'to': "orm['chimere.Area']"}), + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Category']"}), + 'color_theme': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.ColorTheme']", 'null': 'True', 'blank': 'True'}), + 'icon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['chimere.Icon']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'item_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + 'chimere.tinyurl': { + 'Meta': {'object_name': 'TinyUrl'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parameters': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + } + } + + complete_apps = ['chimere'] diff --git a/chimere/models.py b/chimere/models.py index 3556e52..02eee76 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -463,8 +463,8 @@ IFRAME_LINKS = { } class MultimediaFile(models.Model): - name = models.CharField(_(u"Name"), max_length=150, blank=True, null=True) - url = models.CharField(_(u"Url"), max_length=200) + name = models.CharField(_(u"Name"), max_length=150) + url = models.URLField(_(u"Url"), max_length=200) order = models.IntegerField(_(u"Order"), default=1) multimedia_type = models.ForeignKey(MultimediaType) @@ -486,7 +486,7 @@ class MultimediaFile(models.Model): super(MultimediaFile, self).save(*args, **kwargs) class PictureFile(models.Model): - name = models.CharField(_(u"Name"), max_length=150, blank=True, null=True) + name = models.CharField(_(u"Name"), max_length=150) picture = models.ImageField(_(u"Image"), upload_to='pictures', height_field='height', width_field='width') height = models.IntegerField(_(u"Height")) diff --git a/chimere/static/chimere/css/styles.css b/chimere/static/chimere/css/styles.css index 8961760..3b65968 100644 --- a/chimere/static/chimere/css/styles.css +++ b/chimere/static/chimere/css/styles.css @@ -43,7 +43,8 @@ fieldset, .action li, #content, background-color:#FFF; } -div.warning{ +div.warning, +.errors{ background-color:#dbffdb; } @@ -59,6 +60,7 @@ div.warning{ #areas, #detail, #map, div.warning, +div.errors, #content, .action li.selected, #panel, #map-footer{ @@ -451,12 +453,20 @@ ul.subcategories label img{ } div.warning{ - margin-top:18px; - padding:0 10px; + margin:0.2em; + padding:0.2em 10px; +} + +div.errors{ + margin:0.2em; + padding:0.2em; +} + +div.errors ul{ + margin:0; } p.warning{ - text-align:center; } #welcome_button { diff --git a/chimere/templates/chimere/blocks/inline_formset.html b/chimere/templates/chimere/blocks/inline_formset.html index e9e68eb..af0a866 100644 --- a/chimere/templates/chimere/blocks/inline_formset.html +++ b/chimere/templates/chimere/blocks/inline_formset.html @@ -1,12 +1,21 @@ {% load i18n %} + {% if extra_formset.non_form_errors %}<div class='errors'>{{extra_formset.non_form_errors.as_ul}}</div>{% endif %} {{ formset.management_form }} <table class='inline-table'> <caption>{% trans caption %}</caption> - {% for frm in formset%}{%ifequal forloop.counter 1 %} + {% for frm in formset%}{%if forloop.first %} <tr>{% for field in frm%}{% if field.label %} <th>{{field.label}}</th>{% endif %}{%endfor%} - </tr>{%endifequal%} - <tr>{% for field in frm%}{%if field.is_hidden%}{{field}}{% else %} - <td>{{field}}</td>{%endif%}{%endfor%} + </tr>{%endif%} + <tr>{% for field in frm.visible_fields %} + <td>{# Include the hidden fields in the form #} + {% if forloop.first %} + {% for hidden in form.hidden_fields %} + {{ hidden }} + {% endfor %} + {% endif %} + {% if field.errors %}<div class='errors'>{{ field.errors.as_ul }}</div>{% endif %} + {{ field }} + </td>{% endfor %} </tr>{%endfor%} </table> diff --git a/chimere/templates/chimere/edit.html b/chimere/templates/chimere/edit.html index e02d690..355939c 100644 --- a/chimere/templates/chimere/edit.html +++ b/chimere/templates/chimere/edit.html @@ -15,7 +15,7 @@ {% block content %} {% if submited %}{% submited %}{% endif %} - {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} + {% if error_message %}<div class='warning'>{{ error_message }}</div>{% endif %} <fieldset class='edit'> <legend>{% trans "Add/modify a site" %}</legend> <p>* {% trans "indicates a mandatory field" %}</p> @@ -23,12 +23,12 @@ {% csrf_token %} <div class="fieldWrapper"> <label for="id_name">{% trans "Site name"%} *</label> - {{ form.name.errors }} + {% if form.name.errors %}<div class='errors'>{{ form.name.errors }}</div>{% endif %} {{ form.name }} </div> <div class="fieldWrapper"> <label for="id_subcategory">{% trans "Categories" %} *</label> - {{ form.categories.errors }} + {% if form.categories.errors %}<div class='errors'>{{ form.categories.errors }}</div>{% endif %} {{ form.categories }} </div> <div class="fieldWrapper"> @@ -56,6 +56,7 @@ <div class="fieldWrapper"> <label for="id_{{field.name}}">{% trans field.label %}</label> {{ field.errors }} + {% if field.errors %}<div class='errors'>{{ field.errors }}</div>{% endif %} {{ field }} </div> {%endifequal%} diff --git a/chimere/views.py b/chimere/views.py index 59fc3b8..d33f5a9 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -167,9 +167,11 @@ def get_edit_page(redirect_url, item_cls, item_form): notifySubmission(item) response_dct = get_base_response(area_name) return redirect(redirect_url + '-item', - area_name if area_name else '', item.ref_item.pk, - 'submited'),\ - None + area_name if area_name else '', + item.ref_item.pk, 'submited'), None + else: + response_dct['error_message'] = _(u"There are missing field(s)" + u" and/or errors in the submited form.") else: form = item_form(instance=init_item) formset_multi = MultimediaFileFormSet(initial=init_multi, @@ -197,7 +199,6 @@ def edit(request, area_name="", item_id=None, submited=False): response_dct.update({ 'actions':actions, 'action_selected':('contribute', 'edit'), - 'error_message':'', 'map_layer':settings.CHIMERE_MAP_LAYER, 'form':form, 'formset_multi':formset_multi, |