manager: report errors in CSV import using event indexes (#66184)

This commit is contained in:
Valentin Deniaud 2022-09-21 16:10:04 +02:00
parent 7df917588e
commit 445e2ae486
2 changed files with 23 additions and 7 deletions

View File

@ -27,6 +27,7 @@ from dateutil.relativedelta import relativedelta
from django import forms
from django.conf import settings
from django.contrib.auth.models import Group
from django.contrib.humanize.templatetags.humanize import ordinal
from django.core.exceptions import FieldDoesNotExist
from django.core.validators import URLValidator
from django.db import transaction
@ -35,6 +36,7 @@ from django.forms import ValidationError, formset_factory
from django.template import Context, Template, TemplateSyntaxError, VariableDoesNotExist
from django.utils.encoding import force_str
from django.utils.formats import date_format
from django.utils.html import format_html, mark_safe
from django.utils.timezone import localtime, make_aware, now
from django.utils.translation import gettext_lazy as _
@ -1060,6 +1062,11 @@ class ImportEventsForm(forms.Form):
super().__init__(**kwargs)
def clean_events_csv_file(self):
class ValidationErrorWithOrdinal(ValidationError):
def __init__(self, message, event_no):
super().__init__(message)
self.message = format_html(message, event_no=mark_safe(ordinal(event_no + 1)))
content = self.cleaned_data['events_csv_file'].read()
if b'\0' in content:
raise ValidationError(_('Invalid file format.'))
@ -1092,7 +1099,7 @@ class ImportEventsForm(forms.Form):
if not csvline:
continue
if len(csvline) < 3:
raise ValidationError(_('Invalid file format. (line %d)') % (i + 1))
raise ValidationErrorWithOrdinal(_('Invalid file format. ({event_no} event)'), i)
if i == 0 and csvline[0].strip('#') in ('date', 'Date', _('date'), _('Date')):
continue
@ -1146,17 +1153,19 @@ class ImportEventsForm(forms.Form):
event.start_datetime = event_datetime
break
else:
raise ValidationError(_('Invalid file format. (date/time format, line %d)') % (i + 1))
raise ValidationErrorWithOrdinal(
_('Invalid file format. (date/time format, {event_no} event)'), i
)
try:
event.places = int(csvline[2])
except ValueError:
raise ValidationError(_('Invalid file format. (number of places, line %d)') % (i + 1))
raise ValidationError(_('Invalid file format. (number of places, {event_no} event)'), i)
if len(csvline) >= 4:
try:
event.waiting_list_places = int(csvline[3])
except ValueError:
raise ValidationError(
_('Invalid file format. (number of places in waiting list, line %d)') % (i + 1)
_('Invalid file format. (number of places in waiting list, {event_no} event)'), i
)
column_index = 7
@ -1183,13 +1192,13 @@ class ImportEventsForm(forms.Form):
except ValueError:
continue
else:
raise ValidationError(_('Invalid file format. (date/time format, line %d)') % (i + 1))
raise ValidationError(_('Invalid file format. (date/time format, {event_no} event)'), i)
if len(csvline) >= 11 and csvline[10]: # duration is optional
try:
event.duration = int(csvline[10])
except ValueError:
raise ValidationError(_('Invalid file format. (duration, line %d)') % (i + 1))
raise ValidationError(_('Invalid file format. (duration, {event_no} event)'), i)
try:
event.full_clean(exclude=['desk', 'meeting_type', 'primary_event'])

View File

@ -6,6 +6,7 @@ import pytest
import requests
from django.core.management import call_command
from django.db import connection
from django.test import override_settings
from django.test.utils import CaptureQueriesContext
from django.utils.timezone import localtime, make_aware, now
from webtest import Upload
@ -784,7 +785,13 @@ def test_import_events(app, admin_user):
resp.form['events_csv_file'] = Upload('t.csv', b'2016-14-16,18:00,10', 'text/csv')
resp = resp.form.submit(status=200)
assert 'Invalid file format. (date/time format' in resp.text
assert 'Invalid file format. (date/time format, 1st event)' in resp.text
with override_settings(LANGUAGE_CODE='fr-fr'):
resp.form['events_csv_file'] = Upload('t.csv', b'2016-14-16,18:00,10', 'text/csv')
resp = resp.form.submit(status=200)
# ensure <sup> tag is not escaped
assert '1<sup>er</sup>' in resp.text
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,blah', 'text/csv')
resp = resp.form.submit(status=200)