2013-05-08 18:07:09 +02:00
|
|
|
|
#!/usr/bin/env python
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
"""
|
|
|
|
|
openslides.motion.csv_import
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
2013-05-12 00:47:49 +02:00
|
|
|
|
Functions to import motions from a csv file.
|
2013-05-08 18:07:09 +02:00
|
|
|
|
|
|
|
|
|
:copyright: (c) 2011–2013 by the OpenSlides team, see AUTHORS.
|
|
|
|
|
:license: GNU GPL, see LICENSE for more details.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# 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-05-16 00:58:37 +02:00
|
|
|
|
from django.utils.translation import ugettext as _, ugettext_noop
|
2013-05-08 18:07:09 +02:00
|
|
|
|
|
2013-05-12 00:47:49 +02:00
|
|
|
|
from openslides.utils.person.api import Persons
|
|
|
|
|
|
|
|
|
|
from .models import Motion, Category
|
|
|
|
|
|
2013-05-08 18:07:09 +02:00
|
|
|
|
|
2013-05-16 00:58:37 +02:00
|
|
|
|
def import_motions(csv_file, default_submitter, override=False, 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,
|
|
|
|
|
when the flag 'override' is true. If no or multiple categories found,
|
|
|
|
|
the category is set to None.
|
|
|
|
|
"""
|
2013-05-08 18:07:09 +02:00
|
|
|
|
error_messages = []
|
2013-05-12 00:47:49 +02:00
|
|
|
|
warning_messages = []
|
2013-05-08 18:07:09 +02:00
|
|
|
|
count_success = 0
|
2013-05-12 00:47:49 +02:00
|
|
|
|
|
|
|
|
|
# Check encoding
|
|
|
|
|
try:
|
|
|
|
|
csv_file.read().decode('utf8')
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
return (0, [_('Encoding error in import file. Ensure using UTF-8.')], [])
|
2013-05-08 18:07:09 +02:00
|
|
|
|
csv_file.seek(0)
|
2013-05-12 00:47:49 +02:00
|
|
|
|
|
2013-05-08 18:07:09 +02:00
|
|
|
|
with transaction.commit_on_success():
|
|
|
|
|
for (line_no, line) in enumerate(csv.reader(csv_file)):
|
|
|
|
|
if line_no < 1:
|
|
|
|
|
# Do not read the header line
|
|
|
|
|
continue
|
|
|
|
|
|
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:
|
|
|
|
|
error_messages.append(_('Ignoring malformed line %d in import file.') % (line_no + 1))
|
|
|
|
|
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:
|
|
|
|
|
error_messages.append(_('Line %d in import file: Ignoring existing motion.') % (line_no + 1))
|
|
|
|
|
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:
|
|
|
|
|
motion.category = Category.objects.get(name=category)
|
|
|
|
|
except Category.DoesNotExist:
|
|
|
|
|
error_messages.append(_('Line %d in import file: Category not found.') % (line_no + 1))
|
|
|
|
|
except Category.MultipleObjectsReturned:
|
|
|
|
|
error_messages.append(_('Line %d in import file: Multiple categories found.') % (line_no + 1))
|
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:
|
|
|
|
|
for person in Persons():
|
|
|
|
|
if person.clean_name == submitter.decode('utf8'):
|
|
|
|
|
if person_found:
|
|
|
|
|
error_messages.append(_('Line %d in import file: Multiple persons found.') % (line_no + 1))
|
|
|
|
|
person_found = False
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
new_submitter = person
|
|
|
|
|
person_found = True
|
|
|
|
|
if not person_found:
|
|
|
|
|
warning_messages.append(_('Line %d in import file: Default submitter is used.') % (line_no + 1))
|
|
|
|
|
new_submitter = default_submitter
|
|
|
|
|
motion.clear_submitters()
|
|
|
|
|
motion.add_submitter(new_submitter)
|
|
|
|
|
|
2013-05-16 00:58:37 +02:00
|
|
|
|
motion.write_log(message=ugettext_noop('Motion imported'),
|
|
|
|
|
person=importing_person)
|
2013-05-08 18:07:09 +02:00
|
|
|
|
count_success += 1
|
2013-05-12 00:47:49 +02:00
|
|
|
|
|
|
|
|
|
return (count_success, error_messages, warning_messages)
|