From 95acbac316db2fffe37194262e581fc39175a538 Mon Sep 17 00:00:00 2001 From: Nazar Kotjuk Date: Thu, 19 Dec 2013 02:02:11 +0200 Subject: [PATCH] import without creating new objects --- country/signals.py | 25 ++++++ import_xls/custom_forms.py | 88 +------------------- import_xls/excel_settings.py | 116 ++++++++++++++++++-------- import_xls/views.py | 155 ++++++++++++++++------------------- 4 files changed, 182 insertions(+), 202 deletions(-) create mode 100644 country/signals.py diff --git a/country/signals.py b/country/signals.py new file mode 100644 index 00000000..8a4b5fb0 --- /dev/null +++ b/country/signals.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from django.db.models.signals import pre_save, post_save +from models import Country +from django.dispatch import receiver +from django.conf import settings +from functions.form_check import translit_with_separator + +@receiver(post_save) +def country_post_save_handler(sender, **kwargs): + """ + + """ + obj = kwargs['instance'] + if kwargs['created']: + if not obj.url: + obj.url = translit_with_separator(obj.name) + + if not obj.title: + # len(10) is a hack for detect if settings.LANGUAGES is not configured it return all langs + if len(settings.LANGUAGES) in range(10): + for code, name in settings.LANGUAGES: + obj.translate(code) + obj.title = '111' + obj.save() + diff --git a/import_xls/custom_forms.py b/import_xls/custom_forms.py index 93276370..9a711e73 100644 --- a/import_xls/custom_forms.py +++ b/import_xls/custom_forms.py @@ -8,10 +8,10 @@ languages = [code for code in settings.LANGUAGES] class ImportEventForm(forms.Form): excel_file = forms.FileField(label='Выберите файл') - event = forms.ChoiceField(label='Выберите тип события', choices=[('exposition', 'Выставка'), - ('conference', 'Конференция'), - ('seminar', 'Семинар'), - ('webinar', 'Вебинар')]) + event = forms.ChoiceField(label='Выберите тип события', choices=[('exposition.Exposition', 'Выставка'), + ('conference.Conference', 'Конференция'), + ('seminar.Seminar', 'Семинар'), + ('webinar.Webinar', 'Вебинар')]) language = forms.ChoiceField(label='Выберите язык', choices=languages) @@ -33,86 +33,6 @@ class ExportEventForm(forms.Form): theme = forms.ModelMultipleChoiceField(label='Направление', queryset=Theme.objects.all(), required=False) country = forms.ModelMultipleChoiceField(label='Страны', queryset=Country.objects.all(), required=False) - def generate_dicts(self): - data = self.cleaned_data - event = data['event'] - language = data['language'] - date_from = data['date_from'] - date_to = data['date_to'] - theme = data['theme'] - country = data['country'] - # get model of event - model = get_model(event.split('.')[0], event.split('.')[1]) - # - objects = model.objects.language(language).filter(data_begin__range=[date_from, date_to], - country__in=country, - theme__in=theme - ).distinct() - - if not objects: - return None - # get fields - # in list exclude fields - fields = get_all_fields(objects[0],['organiser', 'tag', 'descriptions', 'keywords', 'title', 'theme', - 'users', 'company', 'translations', 'business_program', 'created', - 'modified']) - # readable names - names = get_all_verbose_names(objects[0], fields) - - objects_list = [] - - for object in objects: - obj_dict = {} - # generate dict with field values - for field in fields: - obj_dict = {'name': field, 'value': getattr(object, field), - 'verbose_name': names[field]} - - #obj_dict[field] = {'value': getattr(object, field), 'verbose_name': names[field]} - - objects_list.append(obj_dict) - - return objects_list - - """ - def generate_dicts(self): - data = self.cleaned_data - event = data['event'] - language = data['language'] - date_from = data['date_from'] - date_to = data['date_to'] - theme = data['theme'] - country = data['country'] - # get model of event - model = get_model(event.split('.')[0], event.split('.')[1]) - # - objects = model.objects.language(language).filter(data_begin__range=[date_from, date_to], - country__in=country, - theme__in=theme - ).distinct() - - if not objects: - return None - # get fields - # in list exclude fields - fields = get_all_fields(objects[0],['organiser', 'tag', 'descriptions', 'keywords', 'title', 'theme', - 'users', 'company', 'translations', 'business_program', 'created', - 'modified']) - # readable names - names = get_all_verbose_names(objects[0], fields) - - objects_list = [] - - for object in objects: - obj_dict = {} - # generate dict with field values - for field in fields: - obj_dict[field] = {'value': getattr(object, field), 'verbose_name': names[field]} - - objects_list.append(obj_dict) - - return objects_list - """ def clean_theme(self): """ diff --git a/import_xls/excel_settings.py b/import_xls/excel_settings.py index 716b711b..11e182b8 100644 --- a/import_xls/excel_settings.py +++ b/import_xls/excel_settings.py @@ -21,6 +21,8 @@ def get_audience(value): return 'Специалисты и потребители' elif value == 'general public': return 'Широкая публика' + else: + return '' field_settings = [ {'name': 'id', 'verbose_name': 'id', 'type': get_int, 'width':1500}, @@ -30,7 +32,7 @@ field_settings = [ {'name': 'data_end', 'verbose_name': 'Дата окончания', 'type': str}, {'name': 'main_title', 'verbose_name': 'Краткое описание', 'type': str}, {'name': 'description', 'verbose_name': 'Описание', 'type': str}, - {'name': 'audience', 'verbose_name': 'Аудитория', type: get_audience}, + {'name': 'audience', 'verbose_name': 'Аудитория', 'type': get_audience}, {'name': 'country', 'verbose_name': 'Страна', 'type': str}, {'name': 'city', 'verbose_name': 'Город', 'type': str}, {'name': 'periodic', 'verbose_name': 'Периодичность', 'type': str}, @@ -56,43 +58,87 @@ field_settings = [ ] -def get_cell(field_name, value): - return {'tax': get_bool(value), 'foundation_year': get_int(value), 'max_closed_area': get_int(value), - 'min_closed_equipped_area': get_int(value), 'registration_payment': get_int(value), - 'max_closed_equipped_area': get_int(value), 'max_open_area': get_int(value), 'min_closed_area': get_int(value), - 'min_area': get_int(value), 'canceled_by_administrator': get_bool(value), 'is_published': get_bool(value), - 'min_open_area': get_int(value), 'audience': get_audience(value) - }.get(field_name, str(value)) - - -#--------------------------------------- -#--------------------------------------- - -def get_cell_style(field_name): - font = xlwt.Font() - # Create the Font - font.name = 'Times New Roman' - default_style = xlwt.XFStyle() - # Create the Style - default_style.font = font - return { - - }.get(field_name, default_style) +def to_int(val): + """ + Reverse function to get_int + return None if value isnt integer + """ + try: + return int(val) + except ValueError: + return None -#------------------------------------------ +from country.models import Country +from hvad.utils import get_translation_aware_manager +def to_country(value): + try: + query = get_translation_aware_manager(Country) + country = query.filter(name=value)[0] + return country + except IndexError: + return None -#------------------------------------------ -sorted_names = [u'id', 'name', 'data_begin', 'data_end', 'main_title', 'description', 'country', 'city'] -cols_width = {'id': 1500, 'name':8000} +from city.models import City +def to_city(value): + try: + # get city by name + objects = get_translation_aware_manager(City) + # except IndexError if no found + city = objects.filter(name=value)[0] + return city + except IndexError: + return None + +AUDIENCE1 = ((None,'Не выбрано'), + ('experts', 'Специалисты'), + ('experts and consumers', 'Специалисты и потребители'), + ('general public', 'Широкая публика')) + +def to_audience(value): + try: + if value == 'Специалисты': + return 'experts' + elif value == 'Специалисты и потребители': + return 'experts and consumers' + elif value == 'Широкая публика': + return 'general public' + else: + return '' + except: + return '' -#field_setting.get('width', 20) -def sort_by_names(val): - try: - # put element on the index of sorted names - return sorted_names.index(val) - except ValueError: - # put element on the end - return len(sorted_names) \ No newline at end of file +def get_cell(field_name, value): + return {#'id': int(value), + 'url': str(value), + 'name': str(value), + 'data_begin': str(value), + 'data_end': str(value), + 'main_title': str(value), + 'description': str(value), + 'audience': to_audience(value), + 'country': to_country(value), + 'city': to_city(value), + #'periodic': str(value), + 'web_page': str(value), + 'time': str(value), + 'products': str(value), + 'foundation_year': to_int(value), + 'tax': bool(value), + 'currency': str(value), + 'max_price': to_int(value), + 'min_price': to_int(value), + 'registration_payment': to_int(value), + 'min_closed_area': to_int(value), + 'max_closed_area': to_int(value), + 'min_closed_equipped_area': to_int(value), + 'max_closed_equipped_area': to_int(value), + 'min_open_area': to_int(value), + 'max_open_area': to_int(value), + 'min_area': to_int(value), + 'max_area': to_int(value), + 'is_published': bool(value), + 'canceled_by_administrator': bool(value) + }.get(field_name) diff --git a/import_xls/views.py b/import_xls/views.py index d6cedc70..32224f62 100644 --- a/import_xls/views.py +++ b/import_xls/views.py @@ -3,15 +3,48 @@ from django.core.context_processors import csrf from django.shortcuts import render_to_response from django.http import HttpResponseRedirect, HttpResponse from django.contrib.auth.decorators import login_required +from django.db.models.loading import get_model # import xlwt import xlrd -import tempfile # from custom_forms import ImportEventForm, ExportEventForm +from excel_settings import field_settings, get_cell -from excel_settings import sort_by_names, get_cell_style, get_cell -from excel_settings import cols_width +""" +import_settings = [ + {'name': 'id'}, + {'name': 'url'}, + {'name': 'name'}, + {'name': 'data_begin'}, + {'name': 'data_end'}, + {'name': 'main_title'}, + {'name': 'description'}, + {'name': 'audience'}, + {'name': 'country'}, + {'name': 'city'}, + {'name': 'periodic'}, + {'name': 'web_page'}, + {'name': 'time'}, + {'name': 'products'}, + {'name': 'foundation_year'}, + {'name': 'tax'}, + {'name': 'currency'}, + {'name': 'max_price'}, + {'name': 'min_price'}, + {'name': 'registration_payment'}, + {'name': 'min_closed_area'}, + {'name': 'max_closed_area'}, + {'name': 'min_closed_equipped_area'}, + {'name': 'max_closed_equipped_area'}, + {'name': 'min_open_area'}, + {'name': 'max_open_area'}, + {'name': 'min_area'}, + {'name': 'max_area'}, + {'name': 'is_published'}, + {'name': 'canceled_by_administrator'} + ] +""" @@ -19,14 +52,34 @@ from excel_settings import cols_width def import_event(request): if request.POST: form = ImportEventForm(request.POST, request.FILES) - temp_file = tempfile.TemporaryFile() - import_file = request.FILES.get(request.FILES.keys()[0]) - book = xlrd.open_workbook(file_contents=import_file) - sheet = book.sheet_by_index(0) - row_list = [sheet.row_values(row_number) for row_number in range(sheet.nrows)] - - return HttpResponse(row_list[0]) - + if form.is_valid(): + f = form.cleaned_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[1]] + + # model + model = get_model(request.POST['event'].split('.')[0], request.POST['event'].split('.')[1]) + for row_number, row in enumerate(row_list): + # first two fields are verbose name and name + if row_number > 1: + object = model.objects.language(request.POST['language']).get(id=row[0]) + for col_number, cell in enumerate(row): + value = get_cell(field_names[col_number], cell) + # + if not value: + pass + else: + setattr(object, field_names[col_number], value) + + object.save() + else: + pass + + + return HttpResponse(request.POST['event']) else: form = ImportEventForm() @@ -44,13 +97,6 @@ def xls_to_response(xls, fname): return response -import datetime - - -from excel_settings import field_settings - -from django.db.models.loading import get_model - def export_event(request): if request.POST: form = ExportEventForm(request.POST) @@ -87,18 +133,23 @@ def export_event(request): style.font = font for row, object in enumerate(objects): - for col, field in enumerate(field_settings): + # column number + col = 0 + for field in field_settings: try: value = getattr(object, field['name']) except AttributeError: + # doesnt have such field. exit from iteration continue + if row == 0: # first iteration. set names. set columns width worksheet.write(0, col, field.get('verbose_name', 'default'), style) worksheet.write(1, col, field.get('name'), style) worksheet.col(col).width = field.get('width', 3333) - worksheet.write(row+2, col, field.get('type', str)(value)) + worksheet.write(row+2, col, field.get('type')(value)) + col += 1 return xls_to_response(workbook, 'My Worksheet.xls') else: @@ -110,66 +161,4 @@ def export_event(request): args['form'] = form - return render_to_response('export_event.html', args) -""" -def export_event(request): - if request.POST: - form = ExportEventForm(request.POST) - - if form.is_valid(): - # dict of objects - objects = form.generate_dicts() - return HttpResponse(str(objects)) - - if not objects: - # empty dict - message = 'По даному запросу объектов не найдено' - args = {} - args.update(csrf(request)) - args['message'] = message - args['form'] = form - return render_to_response('export_event.html', args) - - workbook = xlwt.Workbook(encoding = 'utf8') - # new tab - worksheet = workbook.add_sheet('My Worksheet') - - # Create the Font - font = xlwt.Font() - font.name = 'Times New Roman' - font.bold = True - style = xlwt.XFStyle() - # Create the Style - style.font = font - - # get names of fields sorted like in sorted_names list - fields = sorted(objects[0].keys(), key=sort_by_names) - - # generate first row with verbose names - for i, field in enumerate(fields): - worksheet.write(0, i, objects[0][field]['verbose_name'], style) - # generate second row and set columns width - for i, field in enumerate(fields): - worksheet.write(1, i,field, style) - if field in cols_width: - worksheet.col(i).width = cols_width.get(field, 3333) - # fill row with objects - for row, object in enumerate(objects): - for key, value in object.iteritems(): - # current row - col = fields.index(key) - # begins from third row - # get cell formats value (True -> 1, None -> '', ...) - worksheet.write(row+2, col, get_cell(key, value['value']), get_cell_style(key)) - - return xls_to_response(workbook, 'My Worksheet.xls') - else: - form = ExportEventForm() - - args = {} - args.update(csrf(request)) - - args['form'] = form - - return render_to_response('export_event.html', args) -""" \ No newline at end of file + return render_to_response('export_event.html', args) \ No newline at end of file