parent
72847d4d71
commit
cdcf6abcb5
11 changed files with 588 additions and 3 deletions
@ -0,0 +1 @@ |
||||
|
||||
@ -0,0 +1,136 @@ |
||||
# -*- coding: utf-8 -*- |
||||
from django import forms |
||||
from django.conf import settings |
||||
|
||||
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', 'Вебинар')]) |
||||
language = forms.ChoiceField(label='Выберите язык', choices=languages) |
||||
|
||||
|
||||
from theme.models import Theme |
||||
from country.models import Country |
||||
from django.db.models.loading import get_model |
||||
import StringIO |
||||
from functions.translate import get_all_fields, get_all_verbose_names |
||||
|
||||
|
||||
class ExportEventForm(forms.Form): |
||||
event = forms.ChoiceField(label='Выберите тип события', choices=[('exposition.Exposition', 'Выставка'), |
||||
('conference.Conference', 'Конференция'), |
||||
('seminar.Seminar', 'Семинар'), |
||||
('webinar.Webinar', 'Вебинар')]) |
||||
language = forms.ChoiceField(label='Выберите язык', choices=languages) |
||||
date_from = forms.DateField(label='С') |
||||
date_to = forms.DateField(label='До') |
||||
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): |
||||
""" |
||||
Set all themes if no theme selected |
||||
""" |
||||
theme = self.cleaned_data.get('theme') |
||||
if not theme: |
||||
theme = Theme.objects.all() |
||||
|
||||
return theme |
||||
|
||||
|
||||
def clean_country(self): |
||||
""" |
||||
Set all countries if no country selected |
||||
""" |
||||
country = self.cleaned_data.get('country') |
||||
if not country: |
||||
country = Country.objects.all() |
||||
|
||||
return country |
||||
@ -0,0 +1,98 @@ |
||||
# -*- coding: utf-8 -*- |
||||
import xlwt |
||||
import datetime |
||||
|
||||
def get_bool(value): |
||||
if value: |
||||
return 1 |
||||
return 0 |
||||
|
||||
def get_int(value): |
||||
if not value: |
||||
return '' |
||||
return value |
||||
|
||||
def get_audience(value): |
||||
if not value: |
||||
return 'Не выбрано' |
||||
elif value == 'experts': |
||||
return 'Специалисты' |
||||
elif value == 'experts and consumers': |
||||
return 'Специалисты и потребители' |
||||
elif value == 'general public': |
||||
return 'Широкая публика' |
||||
|
||||
field_settings = [ |
||||
{'name': 'id', 'verbose_name': 'id', 'type': get_int, 'width':1500}, |
||||
{'name': 'url', 'verbose_name': 'url', 'type': str}, |
||||
{'name': 'name', 'verbose_name': 'Имя', 'type': str, 'width':8000,}, |
||||
{'name': 'data_begin', 'verbose_name': 'Дата начала', 'type': str}, |
||||
{'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': 'country', 'verbose_name': 'Страна', 'type': str}, |
||||
{'name': 'city', 'verbose_name': 'Город', 'type': str}, |
||||
{'name': 'periodic', 'verbose_name': 'Периодичность', 'type': str}, |
||||
{'name': 'web_page', 'verbose_name': 'Веб страница', 'type': str}, |
||||
{'name': 'time', 'verbose_name': 'Время проведения', 'type': str}, |
||||
{'name': 'products', 'verbose_name': 'Экспонируемые продукты', 'type': str}, |
||||
{'name': 'foundation_year', 'verbose_name': 'Год основания', 'type': get_int}, |
||||
{'name': 'tax', 'verbose_name': 'Налог включен', 'type': get_bool, 'width':1000}, |
||||
{'name': 'currency', 'verbose_name': 'Валюта', 'type': str}, |
||||
{'name': 'max_price', 'verbose_name': 'Максимальная цена', 'type': get_int}, |
||||
{'name': 'min_price', 'verbose_name': 'Минимальная цена', 'type': get_int}, |
||||
{'name': 'registration_payment', 'verbose_name': 'Регистрационный взнос', 'type': get_int}, |
||||
{'name': 'min_closed_area', 'verbose_name': 'Минимальная цена закрытой НЕ оборудованной площади', 'type': get_int}, |
||||
{'name': 'max_closed_area', 'verbose_name': 'Максимальная цена закрытой НЕ оборудованной площади', 'type': get_int}, |
||||
{'name': 'min_closed_equipped_area', 'verbose_name': 'Минимальная цена закрытой оборудованной площади ', 'type': get_int}, |
||||
{'name': 'max_closed_equipped_area', 'verbose_name': 'Максимальная цена закрытой оборудованной площади', 'type': get_int}, |
||||
{'name': 'min_open_area', 'verbose_name': 'Минимальная цена закрытой площади', 'type': get_int}, |
||||
{'name': 'max_open_area', 'verbose_name': 'Максимальная цена открытой площади', 'type': get_int}, |
||||
{'name': 'min_area', 'verbose_name': 'Минимальная площадь', 'type': get_int}, |
||||
{'name': 'max_area', 'verbose_name': 'Максимальная площадь', 'type': get_int}, |
||||
{'name': 'is_published', 'verbose_name': 'Опубликована', 'type': get_bool, 'width':1000}, |
||||
{'name': 'canceled_by_administrator', 'verbose_name': 'Отменена администратором', 'type': get_bool, 'width':1000} |
||||
] |
||||
|
||||
|
||||
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) |
||||
|
||||
#------------------------------------------ |
||||
|
||||
#------------------------------------------ |
||||
sorted_names = [u'id', 'name', 'data_begin', 'data_end', 'main_title', 'description', 'country', 'city'] |
||||
cols_width = {'id': 1500, 'name':8000} |
||||
|
||||
|
||||
#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) |
||||
@ -0,0 +1,175 @@ |
||||
# -*- coding: utf-8 -*- |
||||
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 |
||||
# |
||||
import xlwt |
||||
import xlrd |
||||
import tempfile |
||||
# |
||||
from custom_forms import ImportEventForm, ExportEventForm |
||||
|
||||
from excel_settings import sort_by_names, get_cell_style, get_cell |
||||
from excel_settings import cols_width |
||||
|
||||
|
||||
|
||||
@login_required |
||||
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]) |
||||
|
||||
else: |
||||
form = ImportEventForm() |
||||
|
||||
args = {} |
||||
args.update(csrf(request)) |
||||
args['form'] = form |
||||
return render_to_response('import_event.html', args) |
||||
|
||||
|
||||
|
||||
def xls_to_response(xls, fname): |
||||
response = HttpResponse(mimetype="application/ms-excel") |
||||
response['Content-Disposition'] = 'attachment; filename=%s' % fname |
||||
xls.save(response) |
||||
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) |
||||
if form.is_valid(): |
||||
|
||||
data = form.cleaned_data |
||||
# get model |
||||
model = get_model(data['event'].split('.')[0], data['event'].split('.')[1]) |
||||
# get objects |
||||
objects = model.objects.language(data['language']).filter(data_begin__range=[data['date_from'], data['date_to']], |
||||
country__in=data['country'], |
||||
theme__in=data['theme'] |
||||
).distinct() |
||||
|
||||
if not objects: |
||||
# not found any objects |
||||
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 for first rows |
||||
font = xlwt.Font() |
||||
font.name = 'Times New Roman' |
||||
font.bold = True |
||||
style = xlwt.XFStyle() |
||||
# Create the Style |
||||
style.font = font |
||||
|
||||
for row, object in enumerate(objects): |
||||
for col, field in enumerate(field_settings): |
||||
try: |
||||
value = getattr(object, field['name']) |
||||
except AttributeError: |
||||
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)) |
||||
|
||||
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) |
||||
""" |
||||
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) |
||||
""" |
||||
@ -0,0 +1,92 @@ |
||||
{% extends 'base.html' %} |
||||
{% load static %} |
||||
|
||||
{% block scripts %} |
||||
{# selects #} |
||||
<link href="{% static 'js/select/select2.css' %}" rel="stylesheet"/> |
||||
<script src="{% static 'js/select/select2.js' %}"></script> |
||||
<script src="{% static 'custom_js/make_select.js' %}"></script> |
||||
{# datetimepicker #} |
||||
<link href="{% static 'js/datetimepicker/css/datetimepicker.css' %}" rel="stylesheet"/> |
||||
<script src="{% static 'js/datetimepicker/js/bootstrap-datetimepicker.js' %}"></script> |
||||
<script type="text/javascript"> |
||||
$(document).ready(function(){ |
||||
$('#id_date_from').datetimepicker({ |
||||
todayHighlight: true, |
||||
format : 'dd.mm.yyyy', |
||||
minView:2 |
||||
}); |
||||
$('#id_date_to').datetimepicker({ |
||||
todayHighlight: true, |
||||
format : 'dd.mm.yyyy', |
||||
minView:2 |
||||
}); |
||||
}); |
||||
</script> |
||||
{% endblock %} |
||||
|
||||
{% block body %} |
||||
<form method="post" class="form-horizontal" enctype="multipart/form-data"> {% csrf_token %} |
||||
{# event #} |
||||
<div class="control-group {% if form.event.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.event.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.event }} |
||||
<span class="help-inline">{{ form.event.errors }}</span> |
||||
</div> |
||||
</div> |
||||
{# language #} |
||||
<div class="control-group {% if form.language.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.language.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.language }} |
||||
<span class="help-inline">{{ form.language.errors }}</span> |
||||
</div> |
||||
</div> |
||||
{# date_from #} |
||||
<div class="control-group {% if form.date_from.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.date_from.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.date_from }} |
||||
<span class="help-inline">{{ form.date_from.errors }}</span> |
||||
</div> |
||||
</div> |
||||
{# date_to #} |
||||
<div class="control-group {% if form.date_to.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.date_to.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.date_to }} |
||||
<span class="help-inline">{{ form.date_to.errors }}</span> |
||||
</div> |
||||
</div> |
||||
{# theme #} |
||||
<div class="control-group {% if form.theme.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.theme.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.theme }} |
||||
<span class="help-inline">{{ form.theme.errors }}</span> |
||||
</div> |
||||
</div> |
||||
{# country #} |
||||
<div class="control-group {% if form.country.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.country.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.country }} |
||||
<span class="help-inline">{{ form.country.errors }}</span> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="controls"> |
||||
<input class="btn btn-large btn-primary" type="submit" value="Экспорт"> |
||||
<input class="btn btn-large" type="reset" value="Отмена"> |
||||
</div> |
||||
|
||||
|
||||
</form> |
||||
{% if message %} |
||||
<div class="alert alert-error"> |
||||
{{ message }} |
||||
</div> |
||||
{% endif %} |
||||
|
||||
{% endblock %} |
||||
@ -0,0 +1,42 @@ |
||||
{% extends 'base.html' %} |
||||
{% load static %} |
||||
|
||||
{% block scripts %} |
||||
{% endblock %} |
||||
|
||||
{% block body %} |
||||
<form method="post" class="form-horizontal" enctype="multipart/form-data"> {% csrf_token %} |
||||
|
||||
{# excel_file #} |
||||
<div class="control-group {% if form.excel_file.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.excel_file.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.excel_file }} |
||||
<span class="help-inline">{{ form.excel_file.errors }}</span> |
||||
</div> |
||||
</div> |
||||
{# event #} |
||||
<div class="control-group {% if form.event.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.event.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.event }} |
||||
<span class="help-inline">{{ form.event.errors }}</span> |
||||
</div> |
||||
</div> |
||||
{# language #} |
||||
<div class="control-group {% if form.language.errors %}error{% endif %}"> |
||||
<label class="control-label">{{ form.language.label }}:</label> |
||||
<div class="controls"> |
||||
{{ form.language }} |
||||
<span class="help-inline">{{ form.language.errors }}</span> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="controls"> |
||||
<input class="btn btn-large btn-primary" type="submit" value="Импорт"> |
||||
<input class="btn btn-large" type="reset" value="Отмена"> |
||||
</div> |
||||
|
||||
</form> |
||||
{% endblock %} |
||||
Loading…
Reference in new issue