diff --git a/conference/models.py b/conference/models.py index 75c91e56..b79b5875 100644 --- a/conference/models.py +++ b/conference/models.py @@ -59,6 +59,7 @@ class Conference(TranslatableModel, EventMixin, ExpoMixin): blank=True, null=True, related_name='conference_tags') organiser = models.ManyToManyField('organiser.Organiser', verbose_name='Организатор', blank=True, null=True, related_name='conference_organisers') + org = models.CharField(max_length=255, blank=True, null=True) company = models.ManyToManyField('company.Company', verbose_name='Компании', blank=True, null=True, related_name='conference_companies') users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки', diff --git a/exposition/models.py b/exposition/models.py index 1171f42d..77fb9c4d 100644 --- a/exposition/models.py +++ b/exposition/models.py @@ -71,6 +71,7 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin): blank=True, null=True, related_name='exposition_tags') organiser = models.ManyToManyField('organiser.Organiser', verbose_name='Организатор', blank=True, null=True, related_name='exposition_organisers') + org = models.CharField(max_length=255, blank=True, null=True) company = models.ManyToManyField('company.Company', verbose_name='Компании', blank=True, null=True, related_name='exposition_companies') users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки', diff --git a/functions/signal_handlers.py b/functions/signal_handlers.py index 8e69b737..a0c3a07a 100644 --- a/functions/signal_handlers.py +++ b/functions/signal_handlers.py @@ -6,7 +6,8 @@ from functions.form_check import translit_with_separator def pre_save_handler(sender, **kwargs): obj = kwargs['instance'] url = getattr(obj, 'url') - if url is not None: + + if url: return if hasattr(obj, 'language_code') and obj.language_code =='en': @@ -21,21 +22,6 @@ def pre_save_handler(sender, **kwargs): obj.url = ''.join([random.choice(string.ascii_lowercase) for n in xrange(8)]) - - """ - url = getattr(obj, 'url') - if url: - try: - en_name = obj._meta.translations_model.objects.get(language_code='en', master__id=getattr(obj, 'id')) - obj.url = translit_with_separator(en_name) - except: - pass - - else: - # generate random url if url field is empty - obj.url = ''.join([random.choice(string.ascii_lowercase) for n in xrange(8)]) - """ - def post_save_handler(sender, **kwargs): """ receiver function diff --git a/import_xls/admin.py b/import_xls/admin.py index a2b43cc3..2de38d12 100644 --- a/import_xls/admin.py +++ b/import_xls/admin.py @@ -96,13 +96,17 @@ class ExportCity(ExportView): from exposition.models import Exposition class ImportEvent(FormView): form_class = ImportEventForm - success_url = '/admin/import-event' + success_url = '/admin/import-event/' + template_name = 'admin/import templates/import_event.html' def form_valid(self, form): - result = form.save_file() - Exposition.imports.create_by_dict(result[0]) + errors = form.save_file_debug() messages.success(self.request, 'Success') + context = self.get_context_data() + context['import_errors'] = errors + context['form'] = form + return render_to_response(self.template_name, context) - return super(ImportView, self).form_valid(form) + #return super(ImportEvent, self).form_valid(form) class ImportTheme(ImportView): form_class = ImportThemeForm diff --git a/import_xls/excel_settings.py b/import_xls/excel_settings.py index 43a30a4d..94cab89f 100644 --- a/import_xls/excel_settings.py +++ b/import_xls/excel_settings.py @@ -469,10 +469,10 @@ event_sett = { u'Дата окончания:(YYYY-MM-DD)':{u'field': u'data_end', u'func': to_date}, u'Страна':{u'field': u'country', u'func': to_country}, u'Город':{u'field': u'city_id', u'func': to_city, 'extra_values': 'country'}, - #u'Место проведения':{u'field': u'place', u'func': to_place}, + u'Место проведения':{u'field': u'place', u'func': to_place}, u'ID Тематики':{u'field': u'theme', u'func': to_theme, u'method': True},### u'Теги':{u'field': u'tag', u'func': to_tag, u'method': True}, - #u'Организатор №1':{u'field': u'organiser', u'func': to_tag},#### + u'Организатор №1':{u'field': u'org', u'func': unicode},#### #u'Организатор №2':{u'field': u'organiser', u'func': to_tag},#### u'Описание события':{u'field': u'description', u'func': unicode}, u'Основные темы':{u'field': u'main_themes', u'func': unicode}, diff --git a/import_xls/import_forms.py b/import_xls/import_forms.py index de1a6aa0..27f83514 100644 --- a/import_xls/import_forms.py +++ b/import_xls/import_forms.py @@ -9,6 +9,7 @@ from organiser.models import Organiser from django.db.models.loading import get_model import xlrd, xlwt from excel_settings import import_settings +from functions.form_check import translit_with_separator languages = [code for code in settings.LANGUAGES] @@ -211,6 +212,10 @@ class ImportPlaceConferenceForm(ImportForm): from import_xls.excel_settings import event_sett +typical_errors = {'(1048, "Column \'city_id\' cannot be null")':u'Неправильная страна или город', + '(1048, "Column \'country_id\' cannot be null")':u'Неправильная страна или город', + '(1048, "Column \'data_end\' cannot be null")':u'НЕправильный формат или не заполнена дата окончания', + '(1048, "Column \'data_end\' cannot be null")':u'НЕправильный формат или не заполнена дата начала'} class ImportEventForm(ImportForm): """ @@ -221,40 +226,132 @@ class ImportEventForm(ImportForm): ('conference.Conference', 'Конференция'), ('seminar.Seminar', 'Семинар'), ('webinar.Webinar', 'Вебинар')]) - def save_file(self): - """ - save events from excel file - in language from form - """ + + def save_file_debug(self): data = self.cleaned_data lang = data['language'] f = data['excel_file'] book = xlrd.open_workbook(file_contents=f.read()) sheet = book.sheet_by_index(0) row_list = [sheet.row_values(row_number) for row_number in range(sheet.nrows)] - # all field names in excel file (must be in second row) field_names = [name for name in row_list[0]] # model model = get_model(data['event'].split('.')[0], data['event'].split('.')[1]) - list_dicts = [] + labels = [label for label in row_list[0]] + errors = [] - for row_number, row in enumerate(row_list[1:]): - d = {} + for row_number, row in enumerate(row_list): + if row_number == 0: + continue + + if row[0] != '': + # in first column id + try: + obj = self.model.objects.language(lang).get(id=int(row[0])) + except ValueError: + obj = self.model() + obj.translate(lang) + + except self.model.DoesNotExist: + obj = self.model(id= int(row[0])) + obj.translate(lang) + else: + # if id blank - its a new event + obj = model() + obj.translate(lang) + + methods = [] for col_number, cell in enumerate(row): - # through row - field_name = field_names[col_number] - setting = event_sett.get(field_name) - if setting: - d[setting['field']] = {'value':cell} + # go through row cells + # field name current cell + label = labels[col_number] + + setting = event_sett.get(label) + + if setting is None: + continue + + + if setting.get('method'): + # this cell contains data that must be written after creating object + if cell != "": + methods.append({'func': setting['func'], 'value': cell, 'purpose': setting.get('purpose')}) + continue + + field_name = setting['field'] + func = setting.get('func') + if func is None: + continue + + extra_value = setting.get('extra_values') + if extra_value is not None: + # if setting has extra value then + # it is some field like city, theme, tag + # that has relation and can be created + + # in function we add language(need for relation fields) + # and extra value from object (like for city need country) + try: + extra = getattr(obj, extra_value) + except Exception: + continue + value = func(cell, 'ru', extra) + elif setting.get('bitfield'): + value = func(obj, cell, setting['label']) + else: + value = func(cell) + try: + setattr(obj, field_name, value) + except ValueError: + continue + if not obj.url: + obj.url = translit_with_separator(obj.name) + try: + obj.save() + + except IntegrityError, e: + error = str(e) + if typical_errors.get(error): + error = typical_errors[error] + if error.startswith('(1062, "Duplicate entry') and error.endswith('for key \'url\'")'): + error = u'Событие с таким названием или урлом уже существует' + + errors.append([obj.name, error]) + continue + + for method in methods: + func = method['func'] + if method.get('purpose'): + try: + func(obj, method['value'], method['purpose']) + except: + continue + else: + func(obj, method['value']) - d['lang'] = lang - list_dicts.append(d) + #------------- - return list_dicts + return errors + def save_file(self): + """ + save events from excel file + in language from form + """ + data = self.cleaned_data + lang = data['language'] + f = data['excel_file'] + book = xlrd.open_workbook(file_contents=f.read()) + sheet = book.sheet_by_index(0) + row_list = [sheet.row_values(row_number) for row_number in range(sheet.nrows)] + # all field names in excel file (must be in second row) + field_names = [name for name in row_list[0]] + # model + model = get_model(data['event'].split('.')[0], data['event'].split('.')[1]) + list_dicts = [] for row_number, row in enumerate(row_list): # go through all rows in file @@ -320,7 +417,6 @@ class ImportEventForm(ImportForm): """ #object.save() - sadsa diff --git a/import_xls/utils.py b/import_xls/utils.py index 28babe91..de52aac3 100644 --- a/import_xls/utils.py +++ b/import_xls/utils.py @@ -33,7 +33,10 @@ def to_date(value): try: t = time.strptime(value, "%d.%m.%Y") except ValueError: - t = time.strptime(value, "%d/%m/%Y") + try: + t = time.strptime(value, "%d/%m/%Y") + except ValueError: + return None if isinstance(value, float): t = xlrd.xldate_as_tuple(value, 0)+(0,0,0) @@ -103,6 +106,7 @@ def to_tag(obj,value): def to_place(value): + value = value.replace('/', '') try: place = PlaceExposition.objects.get(url=value) return place diff --git a/templates/admin/import templates/import_event.html b/templates/admin/import templates/import_event.html index 2866f2e7..4216f0ab 100644 --- a/templates/admin/import templates/import_event.html +++ b/templates/admin/import templates/import_event.html @@ -55,6 +55,28 @@ {{ message }} {% endif %} + + {% if import_errors %} +
| Событие | +Ошибка | +
|---|---|
| {{ error.0 }} | +{{ error.1 }} | +