2013-05-08 18:07:09 +02:00
|
|
|
# TODO: Rename the file to 'csv.py' when we drop python2 support. At the moment
|
|
|
|
# the name csv has a conflict with the core-module. See:
|
|
|
|
# http://docs.python.org/2/tutorial/modules.html#intra-package-references
|
|
|
|
|
|
|
|
import csv
|
2013-05-12 00:47:49 +02:00
|
|
|
|
2013-05-08 18:07:09 +02:00
|
|
|
from django.db import transaction
|
2013-09-25 10:01:01 +02:00
|
|
|
from django.utils.translation import ugettext as _
|
|
|
|
from django.utils.translation import ugettext_noop
|
2013-05-08 18:07:09 +02:00
|
|
|
|
2013-05-29 22:29:08 +02:00
|
|
|
from openslides.utils import csv_ext
|
2014-10-11 14:34:49 +02:00
|
|
|
from openslides.users.models import User
|
2013-05-29 22:29:08 +02:00
|
|
|
from openslides.utils.utils import html_strong
|
2013-05-12 00:47:49 +02:00
|
|
|
|
2013-09-25 10:01:01 +02:00
|
|
|
from .models import Category, Motion
|
2013-05-12 00:47:49 +02:00
|
|
|
|
2013-05-08 18:07:09 +02:00
|
|
|
|
2014-03-27 20:30:15 +01:00
|
|
|
def import_motions(csvfile, default_submitter, override, importing_person=None):
|
2013-05-12 00:47:49 +02:00
|
|
|
"""
|
|
|
|
Imports motions from a csv file.
|
2013-05-08 18:07:09 +02:00
|
|
|
|
2013-05-12 00:47:49 +02:00
|
|
|
The file must be encoded in utf8. The first line (header) is ignored.
|
|
|
|
If no or multiple submitters found, the default submitter is used. If
|
|
|
|
a motion with a given identifier already exists, the motion is overridden,
|
2014-03-27 20:30:15 +01:00
|
|
|
when the flag 'override' is True. If no or multiple categories found,
|
2013-05-12 00:47:49 +02:00
|
|
|
the category is set to None.
|
|
|
|
"""
|
2013-05-08 18:07:09 +02:00
|
|
|
count_success = 0
|
2013-05-29 22:29:08 +02:00
|
|
|
count_lines = 0
|
2013-05-12 00:47:49 +02:00
|
|
|
|
|
|
|
# Check encoding
|
|
|
|
try:
|
2014-03-27 20:30:15 +01:00
|
|
|
csvfile.read().decode('utf8')
|
2013-05-12 00:47:49 +02:00
|
|
|
except UnicodeDecodeError:
|
2014-03-27 20:30:15 +01:00
|
|
|
return '', '', _('Import file has wrong character encoding, only UTF-8 is supported!')
|
|
|
|
csvfile.seek(0)
|
2013-05-12 00:47:49 +02:00
|
|
|
|
2014-10-19 10:16:22 +02:00
|
|
|
with transaction.atomic():
|
2014-08-16 09:25:18 +02:00
|
|
|
dialect = csv.Sniffer().sniff(csvfile.readline().decode('utf8'))
|
2013-05-29 22:29:08 +02:00
|
|
|
dialect = csv_ext.patchup(dialect)
|
2014-03-27 20:30:15 +01:00
|
|
|
csvfile.seek(0)
|
2013-11-15 09:00:49 +01:00
|
|
|
all_error_messages = []
|
|
|
|
all_warning_messages = []
|
2014-08-16 09:25:18 +02:00
|
|
|
for (line_no, line) in enumerate(csv.reader(
|
|
|
|
(line.decode('utf8') for line in csvfile.readlines()), dialect=dialect)):
|
2013-11-15 09:00:49 +01:00
|
|
|
warning = []
|
2013-05-08 18:07:09 +02:00
|
|
|
if line_no < 1:
|
|
|
|
# Do not read the header line
|
|
|
|
continue
|
2013-11-15 09:00:49 +01:00
|
|
|
importline = html_strong(_('Line %d:') % (line_no + 1))
|
2013-05-29 22:29:08 +02:00
|
|
|
count_lines += 1
|
2013-05-12 00:47:49 +02:00
|
|
|
# Check format
|
2013-05-08 18:07:09 +02:00
|
|
|
try:
|
2013-05-12 00:47:49 +02:00
|
|
|
(identifier, title, text, reason, submitter, category) = line[:6]
|
2013-05-08 18:07:09 +02:00
|
|
|
except ValueError:
|
2013-05-29 22:29:08 +02:00
|
|
|
msg = _('Line is malformed. Motion not imported. Please check the required values.')
|
2013-11-15 09:00:49 +01:00
|
|
|
all_error_messages.append("%s %s" % (importline, msg))
|
2013-05-08 18:07:09 +02:00
|
|
|
continue
|
|
|
|
|
2013-05-12 00:47:49 +02:00
|
|
|
# Check existing motions according to the identifier
|
2013-05-08 18:07:09 +02:00
|
|
|
if identifier:
|
|
|
|
try:
|
|
|
|
motion = Motion.objects.get(identifier=identifier)
|
|
|
|
except Motion.DoesNotExist:
|
2013-05-12 00:47:49 +02:00
|
|
|
motion = Motion(identifier=identifier)
|
|
|
|
else:
|
|
|
|
if not override:
|
2013-05-29 22:29:08 +02:00
|
|
|
msg = _('Identifier already exists. Motion not imported.')
|
2013-11-15 09:00:49 +01:00
|
|
|
all_error_messages.append("%s %s" % (importline, msg))
|
2013-05-12 00:47:49 +02:00
|
|
|
continue
|
2013-05-08 18:07:09 +02:00
|
|
|
else:
|
|
|
|
motion = Motion()
|
|
|
|
|
2013-05-12 00:47:49 +02:00
|
|
|
# Insert data
|
2013-05-08 18:07:09 +02:00
|
|
|
motion.title = title
|
|
|
|
motion.text = text
|
|
|
|
motion.reason = reason
|
2013-05-12 00:47:49 +02:00
|
|
|
if category:
|
|
|
|
try:
|
2014-05-18 20:17:42 +02:00
|
|
|
category_object = Category.objects.get(name=category)
|
2013-05-12 00:47:49 +02:00
|
|
|
except Category.DoesNotExist:
|
2014-05-18 20:17:42 +02:00
|
|
|
category_object = Category.objects.create(name=category, prefix=category[:1])
|
|
|
|
warning.append(_('Category unknown. New category created.'))
|
2013-05-12 00:47:49 +02:00
|
|
|
except Category.MultipleObjectsReturned:
|
2014-05-18 20:17:42 +02:00
|
|
|
category_object = None
|
2013-11-15 09:00:49 +01:00
|
|
|
warning.append(_('Several suitable categories found. No category is used.'))
|
2014-05-18 20:17:42 +02:00
|
|
|
motion.category = category_object
|
2013-05-08 18:07:09 +02:00
|
|
|
motion.save()
|
2013-05-12 00:47:49 +02:00
|
|
|
|
|
|
|
# Add submitter
|
|
|
|
person_found = False
|
|
|
|
if submitter:
|
2014-10-11 14:34:49 +02:00
|
|
|
for person in User.objects.all():
|
|
|
|
if person.get_short_name() == submitter:
|
2013-05-12 00:47:49 +02:00
|
|
|
if person_found:
|
2013-11-15 09:00:49 +01:00
|
|
|
warning.append(_('Several suitable submitters found.'))
|
2013-05-12 00:47:49 +02:00
|
|
|
person_found = False
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
new_submitter = person
|
|
|
|
person_found = True
|
|
|
|
if not person_found:
|
2013-11-15 09:00:49 +01:00
|
|
|
warning.append(_('Submitter unknown. Default submitter is used.'))
|
2013-05-12 00:47:49 +02:00
|
|
|
new_submitter = default_submitter
|
2013-05-29 22:29:08 +02:00
|
|
|
|
2013-11-15 09:00:49 +01:00
|
|
|
# add all warnings of each csv line to one warning message
|
|
|
|
if warning:
|
|
|
|
warning_message_string = "%s " % importline
|
|
|
|
warning_message_string += " ".join(warning)
|
|
|
|
all_warning_messages.append(warning_message_string)
|
|
|
|
|
2013-05-12 00:47:49 +02:00
|
|
|
motion.clear_submitters()
|
|
|
|
motion.add_submitter(new_submitter)
|
|
|
|
|
2013-05-16 01:14:14 +02:00
|
|
|
motion.write_log(message_list=[ugettext_noop('Motion imported')],
|
2013-05-16 00:58:37 +02:00
|
|
|
person=importing_person)
|
2013-05-08 18:07:09 +02:00
|
|
|
count_success += 1
|
2013-05-12 00:47:49 +02:00
|
|
|
|
2013-11-15 09:00:49 +01:00
|
|
|
# Build final error message with all error items (one bullet point for each csv line)
|
2014-03-27 20:30:15 +01:00
|
|
|
full_error_message = ''
|
2013-11-15 09:00:49 +01:00
|
|
|
if all_error_messages:
|
|
|
|
full_error_message = "%s <ul>" % html_strong(_("Errors"))
|
|
|
|
for error in all_error_messages:
|
|
|
|
full_error_message += "<li>%s</li>" % error
|
|
|
|
full_error_message += "</ul>"
|
|
|
|
|
|
|
|
# Build final warning message with all warning items (one bullet point for each csv line)
|
2014-03-27 20:30:15 +01:00
|
|
|
full_warning_message = ''
|
2013-11-15 09:00:49 +01:00
|
|
|
if all_warning_messages:
|
|
|
|
full_warning_message = "%s <ul>" % html_strong(_("Warnings"))
|
|
|
|
for warning in all_warning_messages:
|
|
|
|
full_warning_message += "<li>%s</li>" % warning
|
|
|
|
full_warning_message += "</ul>"
|
|
|
|
|
2014-03-27 20:30:15 +01:00
|
|
|
# Build final success message
|
|
|
|
if count_success:
|
|
|
|
success_message = '<strong>%s</strong><br>%s' % (
|
|
|
|
_('Summary'),
|
|
|
|
_('%(counts)d of %(total)d motions successfully imported.')
|
|
|
|
% {'counts': count_success, 'total': count_lines})
|
|
|
|
else:
|
|
|
|
success_message = ''
|
|
|
|
|
|
|
|
return success_message, full_warning_message, full_error_message
|