diff --git a/city/models.py b/city/models.py index e02547f6..aa4f4ead 100644 --- a/city/models.py +++ b/city/models.py @@ -2,6 +2,7 @@ from datetime import date from django.db import models from django.db.models.signals import post_save, pre_save +from django.utils import translation from hvad.models import TranslatableModel, TranslatedFields, TranslationManager from bitfield import BitField from sorl.thumbnail import ImageField @@ -116,6 +117,12 @@ class City(TranslatableModel): def get_sub_categories(self): return [] + def get_index_text(self): + translation.activate('ru') + translations = self.translations.all() + names = ' '.join([tr.name for tr in translations]) + return names + diff --git a/city/search_indexes.py b/city/search_indexes.py index c9c457d3..8d54a854 100644 --- a/city/search_indexes.py +++ b/city/search_indexes.py @@ -1,18 +1,36 @@ +# -*- coding: utf-8 -*- +from django.utils import translation from haystack import indexes from models import City +from functions.search_mixin import ExpoSearchMixin -""" -class CityIndex(indexes.SearchIndex, indexes.Indexable): + +class CountryIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin): text = indexes.CharField(document=True, use_template=True) - translations = indexes.MultiValueField() - #name = indexes.CharField(model_attr='translations__name') + url = indexes.CharField() + content_auto = indexes.EdgeNgramField() + form_name = indexes.CharField() + # translated fields + name_en = indexes.CharField() + name_ru = indexes.CharField() + catalog_name_en = indexes.CharField() + catalog_name_ru = indexes.CharField() + + def prepare_form_name(self, obj): + return 'ci' + + def prepare_catalog_name_en(self, obj): + return u'Cities' - def prepare_translations(self, obj): - return [tr.name for tr in obj.translations.all()] + def prepare_catalog_name_ru(self, obj): + return u'Города' def get_model(self): return City def index_queryset(self, using=None): - return self.get_model().objects.filter() -""" + + return self.get_model().used.all() + + def get_updated_field(self): + return 'modified' \ No newline at end of file diff --git a/conference/admin.py b/conference/admin.py index c1bfa2b1..f0f6a20d 100644 --- a/conference/admin.py +++ b/conference/admin.py @@ -239,7 +239,7 @@ class ConferenceView(AdminView): 'link':obj.link, 'conference_id':obj.id, 'expohit': obj.expohit, 'periodic':obj.periodic, 'discount': obj.discount,'canceled': obj.canceled, 'moved': obj.moved, 'visitors': obj.visitors, 'members': obj.members, 'logo': obj.logo, - 'audience':[item for item, bool in obj.audience if bool==True], + 'audience':[item for item, bool in obj.audience if bool==True], 'org': obj.org, 'quality_label': [item for item, bool in obj.quality_label if bool==True]} if obj.place: diff --git a/conference/forms.py b/conference/forms.py index 98c08645..12040fc2 100644 --- a/conference/forms.py +++ b/conference/forms.py @@ -47,9 +47,9 @@ class ConferenceCreateForm(forms.Form): data_end = forms.DateField(label=u'Дата окончания', input_formats=['%Y-%m-%d', '%d.%m.%Y']) logo = forms.ImageField(label='Logo', required=False) - organiser = forms.MultipleChoiceField(label=u'Организаторы', required=False, - choices=[(item.id, item.name) for item in Organiser.objects.language().all()]) - + #organiser = forms.MultipleChoiceField(label=u'Организаторы', required=False, + # choices=[(item.id, item.name) for item in Organiser.objects.language().all()]) + org = forms.CharField(required=False, label=u'Организатор') country = forms.ChoiceField(label=u'Страна', choices=[(c.id, c.name) for c in Country.objects.all()]) theme = forms.MultipleChoiceField(label='Тематики', choices=[(item.id, item.name) for item in Theme.objects.language().all()]) @@ -140,6 +140,7 @@ class ConferenceCreateForm(forms.Form): if data.get('logo'): conference.logo = data['logo'] + conference.org = data['org'] conference.data_begin = data['data_begin'] conference.data_end = data['data_end'] conference.link = data['link'] diff --git a/conference/search_indexes.py b/conference/search_indexes.py index 3266fb52..bdce191b 100644 --- a/conference/search_indexes.py +++ b/conference/search_indexes.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- from haystack import indexes from models import Conference +from functions.search_mixin import ExpoSearchMixin -class ConferenceIndex(indexes.SearchIndex, indexes.Indexable): +class ConferenceIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin): text = indexes.CharField(document=True, use_template=True) where = indexes.MultiValueField() url = indexes.CharField() @@ -31,13 +32,6 @@ class ConferenceIndex(indexes.SearchIndex, indexes.Indexable): def prepare_catalog_name_ru(self, obj): return u'Конференции' - - def prepare_where(self, obj): - country = [tr.name for tr in obj.country.translations.all()] - city = [tr.name for tr in obj.city.translations.all()] - - return country + city - def get_model(self): return Conference diff --git a/conference/urls.py b/conference/urls.py index 439fa230..77279394 100644 --- a/conference/urls.py +++ b/conference/urls.py @@ -66,6 +66,8 @@ urlpatterns = patterns('', url(r'conference/(?P.*)/members/page/(?P\d+)/$', ConferenceMembers.as_view()), url(r'conference/(?P.*)/members/$', ConferenceMembers.as_view()), url(r'^conference/(?P.*)/service/thanks/', ConferenceThankView.as_view()), + url(r'^conference/(?P.*)/service/visit/', 'conference.views.visit_redirect'), + url(r'conference/(?P.*)/service/(?P.*)/', ConferenceServiceView.as_view()), diff --git a/conference/views.py b/conference/views.py index 3363cc12..c01ce80c 100644 --- a/conference/views.py +++ b/conference/views.py @@ -2,7 +2,7 @@ import json import datetime from django.conf import settings -from django.http import HttpResponse, Http404, HttpResponseRedirect +from django.http import HttpResponse, Http404, HttpResponseRedirect, HttpResponsePermanentRedirect from django.contrib import messages from django.shortcuts import get_object_or_404 from django.contrib.contenttypes.models import ContentType @@ -287,6 +287,12 @@ class ConferenceThankView(MetadataMixin, DetailView): slug_field = 'url' template_name = 'client/service/thank_u_page.html' +def visit_redirect(request, slug): + obj = get_object_or_404(Conference, url=slug) + redirect = obj.get_permanent_url() + return HttpResponsePermanentRedirect(redirect) + + class ConferenceServiceView(FormMixin, DetailView): model = Conference slug_field = 'url' diff --git a/country/manager.py b/country/manager.py index b267551f..fde5ca56 100644 --- a/country/manager.py +++ b/country/manager.py @@ -93,6 +93,13 @@ class CountryManager(TranslationManager): cache.set(key, countries, self.cache_time) return countries + def countries_for_search(self): + lang = translation.get_language() + qs = super(CountryManager, self).select_related('exposition_country').\ + filter(exposition_country__country__isnull=False, translations__language_code=lang, )\ + .order_by('translations__name').distinct() + return qs + class AreaManager(TranslationManager): def all_sorted(self): diff --git a/country/models.py b/country/models.py index 738db7e7..36bb5a99 100644 --- a/country/models.py +++ b/country/models.py @@ -55,6 +55,12 @@ class Area(TranslatableModel): parent = {} return parent + def get_index_text(self): + translation.activate('ru') + translations = self.translations.all() + names = ' '.join([tr.name for tr in translations]) + return names + class Country(TranslatableModel): """ @@ -161,6 +167,12 @@ class Country(TranslatableModel): parent = {'text' : self.area.name, 'id': self.area.id, 'name': 'area'} return parent + def get_index_text(self): + translation.activate('ru') + translations = self.translations.all() + names = ' '.join([tr.name for tr in translations]) + return names + pre_save.connect(pre_save_handler, sender=Country) diff --git a/country/search_indexes.py b/country/search_indexes.py new file mode 100644 index 00000000..0debd42a --- /dev/null +++ b/country/search_indexes.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from django.utils import translation +from haystack import indexes +from models import Country, Area +from functions.search_mixin import ExpoSearchMixin + + +class CountryIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin): + text = indexes.CharField(document=True, use_template=True) + url = indexes.CharField() + content_auto = indexes.EdgeNgramField() + form_name = indexes.CharField() + # translated fields + name_en = indexes.CharField() + name_ru = indexes.CharField() + catalog_name_en = indexes.CharField() + catalog_name_ru = indexes.CharField() + + def prepare_form_name(self, obj): + return 'co' + + def prepare_catalog_name_en(self, obj): + return u'Countries' + + def prepare_catalog_name_ru(self, obj): + return u'Страны' + + def get_model(self): + return Country + + def index_queryset(self, using=None): + + return self.get_model().objects.countries_for_search() + + def get_updated_field(self): + return 'modified' + +class AreaIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin): + text = indexes.CharField(document=True, use_template=True) + content_auto = indexes.EdgeNgramField() + form_name = indexes.CharField() + # translated fields + name_en = indexes.CharField() + name_ru = indexes.CharField() + catalog_name_en = indexes.CharField() + catalog_name_ru = indexes.CharField() + + def prepare_form_name(self, obj): + return 'area' + + def prepare_catalog_name_en(self, obj): + return u'Areas' + + def prepare_catalog_name_ru(self, obj): + return u'Регионы' + + def get_model(self): + return Area + + def index_queryset(self, using=None): + + return self.get_model().objects.filter() \ No newline at end of file diff --git a/exposition/admin.py b/exposition/admin.py index 7bdf2d09..3d1d2c3c 100644 --- a/exposition/admin.py +++ b/exposition/admin.py @@ -277,7 +277,7 @@ class ExpositionView(AdminView): 'min_stand_size':obj.min_stand_size, 'application_deadline':obj.application_deadline, 'min_open_area':obj.min_open_area, 'max_open_area':obj.max_open_area, 'registration_payment':obj.registration_payment, 'exposition_id':obj.id, - 'registration_link': obj.registration_link, + 'registration_link': obj.registration_link, 'org': obj.org, 'expohit': obj.expohit, 'discount': obj.discount, 'canceled': obj.canceled, 'moved': obj.moved, 'logo': obj.logo, 'visitors': obj.visitors, 'members': obj.members, diff --git a/exposition/forms.py b/exposition/forms.py index d588c80d..990fc457 100644 --- a/exposition/forms.py +++ b/exposition/forms.py @@ -49,11 +49,12 @@ class ExpositionCreateForm(forms.Form): data_end = forms.DateField(label=u'Дата окончания', input_formats=['%Y-%m-%d', '%d.%m.%Y']) logo = forms.ImageField(label='Logo', required=False) - organiser = forms.MultipleChoiceField(label=u'Организаторы', required=False, - choices=[(item.id, item.name) for item in Organiser.objects.language().all()]) + #organiser = forms.MultipleChoiceField(label=u'Организаторы', required=False, + # choices=[(item.id, item.name) for item in Organiser.objects.language().all()]) + org = forms.CharField(required=False, label=u'Организатор') - company = forms.MultipleChoiceField(label=u'Компании', required=False, - choices=[(item.id, item.name) for item in Company.objects.language().all()] ) + #company = forms.MultipleChoiceField(label=u'Компании', required=False, + # choices=[(item.id, item.name) for item in Company.objects.language().all()] ) country = forms.ChoiceField(label=u'Страна', choices=[(c.id, c.name) for c in Country.objects.all()]) theme = forms.MultipleChoiceField(label='Тематики', choices=[(item.id, item.name) for item in Theme.objects.language().all()]) @@ -62,7 +63,6 @@ class ExpositionCreateForm(forms.Form): #creates select input with empty choices cause it will be filled with ajax city = forms.CharField(label=u'Город', widget=forms.HiddenInput()) tag = forms.CharField(label=u'Теги', widget=forms.HiddenInput(), required=False) - #tag = forms.MultipleChoiceField(label=u'Теги', required=False) periodic = forms.ChoiceField(label=u'Периодичность', choices=PERIODIC, required=False) audience = forms.MultipleChoiceField(label=u'Аудитория', choices=public, initial='', required=False) @@ -169,7 +169,7 @@ class ExpositionCreateForm(forms.Form): exposition.theme.clear() exposition.tag.clear() exposition.organiser.clear() - exposition.company.clear() + #exposition.company.clear() #simple fields if not getattr(exposition, 'url'): @@ -177,6 +177,7 @@ class ExpositionCreateForm(forms.Form): if data.get('logo'): exposition.logo = data['logo'] + exposition.org = data['org'] exposition.data_begin = data['data_begin'] exposition.data_end = data['data_end'] exposition.periodic = data['periodic'] @@ -236,7 +237,7 @@ class ExpositionCreateForm(forms.Form): exposition.theme.add(*data['theme']) exposition.tag.add(*Tag.objects.filter(id__in=data['tag'])) exposition.organiser.add(*Organiser.objects.filter(id__in=data.get('organiser', []))) - exposition.company.add(*Company.objects.filter(id__in=data.get('company', []))) + #exposition.company.add(*Company.objects.filter(id__in=data.get('company', []))) exposition.save() diff --git a/exposition/models.py b/exposition/models.py index 286c4481..dce42537 100644 --- a/exposition/models.py +++ b/exposition/models.py @@ -72,6 +72,7 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin): 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) + place_alt = 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/exposition/search_indexes.py b/exposition/search_indexes.py index 630015b9..639a9c7e 100644 --- a/exposition/search_indexes.py +++ b/exposition/search_indexes.py @@ -40,15 +40,5 @@ class ExpositionIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin): return self.get_model().objects.filter(is_published=True) - def get_name(self): - return 123 - lang = translation.get_language() - if lang == 'ru': - return self.name_ru - elif lang=='en': - return self.name_en - else: - return self.name_ru - def get_updated_field(self): return 'modified' \ No newline at end of file diff --git a/exposition/urls.py b/exposition/urls.py index cad06b17..5290ea71 100644 --- a/exposition/urls.py +++ b/exposition/urls.py @@ -72,6 +72,7 @@ urlpatterns = patterns('', url(r'^expo/(?P.*)/members/page/(?P\d+)/$', ExpoMembers.as_view(), {'meta_id':63}), url(r'^expo/(?P.*)/members/$', ExpoMembers.as_view(), {'meta_id':63}), url(r'^expo/(?P.*)/service/thanks/', ExpositionThankView.as_view()), + url(r'^expo/(?P.*)/service/visit/', 'exposition.views.visit_redirect'), url(r'^expo/(?P.*)/service/(?P.*)/', ExpositionServiceView.as_view()), # expo list url(r'^expo/(?P\d+)/(?P.*)/page/(?P\d+)/$', ExpoList.as_view(), {'meta_id':4}), diff --git a/exposition/views.py b/exposition/views.py index 98dac122..f5c8f113 100644 --- a/exposition/views.py +++ b/exposition/views.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import json import datetime -from django.http import HttpResponseRedirect, HttpResponse +from django.http import HttpResponseRedirect, HttpResponse, HttpResponsePermanentRedirect from django.contrib import messages from django.contrib.contenttypes.models import ContentType from django.conf import settings @@ -182,6 +182,11 @@ class ExpositionThankView(MetadataMixin, DetailView): slug_field = 'url' template_name = 'client/service/thank_u_page.html' +def visit_redirect(request, slug): + obj = get_object_or_404(Exposition, url=slug) + redirect = obj.get_permanent_url() + 'price/' + return HttpResponsePermanentRedirect(redirect) + class ExpositionServiceView(MetadataMixin, FormMixin, DetailView): model = Exposition slug_field = 'url' diff --git a/functions/model_mixin.py b/functions/model_mixin.py index 36b120b4..f56f145c 100644 --- a/functions/model_mixin.py +++ b/functions/model_mixin.py @@ -32,8 +32,11 @@ class EventMixin(object): url = '%s%s/'%(self.get_catalog_url(), self.url) return url - - + def org_split(self): + if self.org: + return self.org.split(';') + else: + return [] def get_logo(self): return self.logo diff --git a/functions/search_forms.py b/functions/search_forms.py index fc0d34a7..f54491b9 100644 --- a/functions/search_forms.py +++ b/functions/search_forms.py @@ -279,7 +279,7 @@ class ExpositionSearchForm(AbstactSearchForm): area = self.cleaned_data.get('area') - sqs = SearchQuerySet().models(Exposition).all() + sqs = SearchQuerySet().models(Exposition, Conference).all() if fr: sqs = sqs.filter(data_begin__gte=fr) diff --git a/import_xls/admin.py b/import_xls/admin.py index eaca4eab..0ceee351 100644 --- a/import_xls/admin.py +++ b/import_xls/admin.py @@ -13,8 +13,10 @@ from import_forms import ImportEventForm, ImportThemeForm, ImportTagForm, Import from export_forms import ExportEventForm, ExportOrganiserForm, ExportThemeForm, ExportTagForm,\ ExportUserForm, ExportCompanyForm, ExportPlaceConferenceForm, ExportPlaceExpositionForm, ExportBlogForm,\ ExportCityForm -from django.views.generic import FormView +from django.views.generic import FormView, ListView, DeleteView +from django.conf import settings from django.contrib import messages +from django.shortcuts import get_object_or_404 def xls_to_response(xls, fname): response = HttpResponse(mimetype="application/ms-excel") @@ -97,20 +99,23 @@ class ExportCity(ExportView): -from exposition.models import Exposition +from import_xls.models import Log class ImportEvent(FormView): form_class = ImportEventForm success_url = '/admin/import-event/' template_name = 'admin/import templates/import_event.html' def form_valid(self, form): + 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 HttpResponseRedirect('/admin/import/log/') + + #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(ImportEvent, self).form_valid(form) class ImportTheme(ImportView): form_class = ImportThemeForm @@ -135,4 +140,34 @@ class ImportPlaceConference(ImportView): class ExportEvent(ExportView): form_class = ExportEventForm template_name = 'export_event.html' - success_url = '/admin/export-event' \ No newline at end of file + success_url = '/admin/export-event' + + +class LogList(ListView): + model = Log + paginate_by = settings.ADMIN_PAGINATION + template_name = 'admin/import templates/log.html' + +class LogDelete(DeleteView): + model = Log + success_url = '/admin/import/log/' + template_name = 'admin/import templates/log_delete.html' + + +def log_file(request, log_id): + log = get_object_or_404(Log, id=log_id) + response = HttpResponse() + response['content-type'] = 'application/x-executable' + filename = 'import_%s_log.txt'%str(log.id) + response['content-disposition'] = 'attachment;filename=%s'%filename + response['X-Accel-Redirect'] = log.log.url + return response + +def work_file(request, log_id): + log = get_object_or_404(Log, id=log_id) + response = HttpResponse() + response['content-type'] = 'application/x-executable' + filename = 'import_%s_file.xls'%str(log.id) + response['content-disposition'] = 'attachment;filename=%s'%filename + response['X-Accel-Redirect'] = log.work_file.url + return response \ No newline at end of file diff --git a/import_xls/admin_urls.py b/import_xls/admin_urls.py index baf65303..0d7af157 100644 --- a/import_xls/admin_urls.py +++ b/import_xls/admin_urls.py @@ -2,8 +2,11 @@ from django.conf.urls import patterns, url from admin import ImportTheme, ImportEvent, ImportOrganiser, ImportTag, ImportPlaceExposition, ImportPlaceConference + from admin import ExportTheme, ExportEvent, ExportOrganiser, ExportTag, ExportPlaceExposition,\ - ExportPlaceConference, ExportCompany, ExportUser, ExportBlog, ExportCity + ExportPlaceConference, ExportCompany, ExportUser, ExportBlog, ExportCity, LogList +from import_xls.admin import LogDelete + urlpatterns = patterns('', url(r'^import-event/$', ImportEvent.as_view()), @@ -23,5 +26,8 @@ urlpatterns = patterns('', url(r'^export-company/$', ExportCompany.as_view()), url(r'^export-blog/$', ExportBlog.as_view()), url(r'^export-city/$', ExportCity.as_view()), + url(r'^import/log/$', LogList.as_view()), + url(r'^import/log/delete/(?P.*)/$', LogDelete.as_view()), + url(r'^log/log/(?P.*)/$', 'import_xls.admin.log_file'), + url(r'^log/work_file/(?P.*)/$', 'import_xls.admin.work_file'), ) - diff --git a/import_xls/import_forms.py b/import_xls/import_forms.py index 9ed993a7..7d390652 100644 --- a/import_xls/import_forms.py +++ b/import_xls/import_forms.py @@ -246,6 +246,15 @@ typical_errors = {'(1048, "Column \'city_id\' cannot be null")':u'Неправи '(1048, "Column \'data_end\' cannot be null")':u'НЕправильный формат или не заполнена дата начала'} # event +import time +def logcall(f, msg): + with open(f.file.name, 'a') as logfile: + logfile.write(msg.encode('utf8')) + + + + +from import_xls.models import Log class ImportEventForm(ImportForm): """ extended form for importing one type of event @@ -270,10 +279,12 @@ class ImportEventForm(ImportForm): labels = [label for label in row_list[0]] errors = [] + log = Log.custom.create_log_name(f) for row_number, row in enumerate(row_list): if row_number == 0: continue + log_msg = u'[%s] %s: '%(str(row_number), row[2]) if row[0] != '': # in first column id try: @@ -305,7 +316,8 @@ class ImportEventForm(ImportForm): 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')}) + methods.append({'func': setting['func'], 'value': cell, + 'purpose': setting.get('purpose'), 'field': label}) continue field_name = setting['field'] @@ -316,7 +328,7 @@ class ImportEventForm(ImportForm): 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 + # it is some field like city, tag # that has relation and can be created # in function we add language(need for relation fields) @@ -332,8 +344,8 @@ class ImportEventForm(ImportForm): else: value = func(cell) - if field_name != 'place': + if field_name != 'place': try: setattr(obj, field_name, value) except ValueError: @@ -351,15 +363,17 @@ class ImportEventForm(ImportForm): obj.is_published = True 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]) + log_msg += error + logcall(log.log, log_msg + '\n') continue for method in methods: @@ -368,12 +382,14 @@ class ImportEventForm(ImportForm): try: func(obj, method['value'], method['purpose']) except: + log_msg += '(%s: Ошибка);'%method['field'] continue else: - func(obj, method['value']) - - #------------- + msg = func(obj, method['value']) + if msg: + log_msg += '(%s: %s);'%(method['field'], msg) + logcall(log.log, log_msg + '\n') return errors def save_file(self): diff --git a/import_xls/models.py b/import_xls/models.py new file mode 100644 index 00000000..8bb0d818 --- /dev/null +++ b/import_xls/models.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +from django.db import models +from django.conf import settings +from django.db.models.fields.files import FieldFile +from django.db.models.signals import pre_delete + +def get_doc_dir(instance, filename): + from pytils import translit + return u'import_xls/import/%s' %translit.translify(filename) + + +def file_cleanup(sender, instance, *args, **kwargs): + ''' + Deletes the file(s) associated with a model instance. The model + is not saved after deletion of the file(s) since this is meant + to be used with the pre_delete signal. + ''' + for field_name, _ in instance.__dict__.iteritems(): + field = getattr(instance, field_name) + if issubclass(field.__class__, FieldFile) and field.name: + field.delete(save=False) + +class LogManager(models.Manager): + def create_log(self, work_file, errors): + """ + + :param work_file: executing file + :param errors: list of errors ([{'event name':['err1', 'err2']}]) + :return: object log + """ + LOG_DIRECTORY = settings.MEDIA_ROOT+'import_xls/logs/' + name= '111.txt' + filename = LOG_DIRECTORY + name + + log_file = open(filename, "w") + for error in errors: + event_name = ';'.join(error.keys()) + errs = '' + for err in error.values(): + errs += '; '.join(err) + errs += ';' + + log_file.write('%s: %s\n'%(event_name, errs)) + + log_file.close() + #update.log_file.name = 'updates/'+name + log = Log(work_file=work_file) + log.log.name = 'import_xls/logs/' + name + #log = Log.objects.create(work_file=work_file, log=log_file) + log.save() + return log + + def create_log_name(self, work_file): + log = Log.objects.create(work_file=work_file) + LOG_DIRECTORY = settings.MEDIA_ROOT+'import_xls/logs/' + name= 'log_%d.log'%log.id + filename = LOG_DIRECTORY + name + log_file = open(filename, "w").close() + log.log.name = 'import_xls/logs/' + name + log.save() + return log + + +class Log(models.Model): + work_file = models.FileField(upload_to=get_doc_dir) + log = models.FileField(upload_to='import_xls/logs/', blank=True) + type = models.CharField(max_length=10, default='IMPORT') + created = models.DateTimeField(auto_now_add=True) + + objects = models.Manager() + custom = LogManager() + + class Meta: + ordering = ['-created'] + +pre_delete.connect(file_cleanup, sender=Log) + diff --git a/import_xls/utils.py b/import_xls/utils.py index 1951086d..334f9608 100644 --- a/import_xls/utils.py +++ b/import_xls/utils.py @@ -89,9 +89,13 @@ def to_theme(obj, value): theme_ids = value.split(',') if theme_ids == ['']: - return + return u'Неправильное значение' obj.theme.clear() obj.theme.add(*Theme.objects.filter(id__in=theme_ids)) + if not Theme.objects.filter(id__in=theme_ids).exists(): + return u'Нет совпадений' + return None + def to_tag(obj,value): if value == [""]: @@ -101,8 +105,7 @@ def to_tag(obj,value): if names: obj.tag.clear() obj.tag.add(*Tag.objects.filter(translations__name__in=names, theme__in=obj.theme.all())) - else: - return + return None @@ -171,7 +174,7 @@ def save_logo(obj, path): try: alt_name = get_alternative_filename(full_path, file_name) except UnicodeEncodeError: - return None + return u'Некоректное название файла' download_to = full_path+alt_name @@ -197,14 +200,14 @@ def save_logo(obj, path): f.close() except: # can be timeout - return None + return u'Превышено время ожидания' obj.logo = logo_path + alt_name try: obj.save() except: print('logo exception. logo: %s'%obj.logo) - return None + return u'Неизвестная ошибка' @@ -213,10 +216,10 @@ def check_quality_label(obj, value, label): try: value = int(value) except: - return bit + return None if value: setattr(bit, label, True) - return bit + return None def to_user(value): try: diff --git a/proj/admin_urls.py b/proj/admin_urls.py index b9684a90..0e66313d 100644 --- a/proj/admin_urls.py +++ b/proj/admin_urls.py @@ -31,6 +31,8 @@ urlpatterns = required( url(r'^webinar/', include('webinar.admin_urls')), url(r'^settings/', include('settings.admin_urls')), url(r'^meta/', include('meta.admin_urls')), + url(r'^import_xls/', include('import_xls.admin_urls')), + url(r'^language/add/', 'directories.admin.language_add'), url(r'^currency/add/', 'directories.admin.currency_add'), # ajax requests diff --git a/proj/settings.py b/proj/settings.py index e0e21c5d..1268efa5 100644 --- a/proj/settings.py +++ b/proj/settings.py @@ -284,6 +284,7 @@ INSTALLED_APPS = ( 'directories', 'exposition', 'file', + 'import_xls', 'news', 'note', 'organiser', diff --git a/settings/templatetags/template_filters.py b/settings/templatetags/template_filters.py index b013912e..fb26e631 100644 --- a/settings/templatetags/template_filters.py +++ b/settings/templatetags/template_filters.py @@ -160,6 +160,10 @@ def random_social(value): def random3(value): return random.randrange(0,3) +@register.filter +def random4(value): + return random.randrange(0,4) + @register.filter def random5(value): return random.randrange(0,5) diff --git a/settings/views.py b/settings/views.py index a2d22475..0655f9c3 100644 --- a/settings/views.py +++ b/settings/views.py @@ -10,6 +10,7 @@ from theme.models import Tag, Theme from place_exposition.models import PlaceExposition from place_conference.models import PlaceConference from company.models import Company +from conference.models import Conference # every this model must have method get_subcategories categories = {'area':{'sub':True, 'model':Area, 'sub_categorie_name':'co'}, @@ -43,17 +44,20 @@ def search_autocomplete(request): term = request.GET['term'] form = request.GET['form'] if form == 'place': - areas = [{'text':item.name, 'id':item.id, 'name':'area'} for item in Area.objects.filter(translations__name__contains=term)] - countries = [{'text':item.name, 'id':item.id, 'name':'co'} for item in Country.objects.select_related('exposition_country')\ - .filter(exposition_country__country__isnull=False, translations__language_code=lang, translations__name__contains=term).distinct()] - cities = [{'text':item.name, 'id':item.id, 'name':'ci'} for item in City.objects.select_related('exposition_city')\ - .filter(exposition_city__city__isnull=False, translations__language_code=lang, translations__name__contains=term).distinct()] - - objects = areas + countries + cities - return HttpResponse(json.dumps(objects), content_type='application/json') + qs = list(SearchQuerySet().models(Country, City, Area).autocomplete(content_auto=term)[:6]) + objects = [{'text':get_by_lang(item, 'name', lang), 'id': item.pk, 'name': item.form_name} for item in qs] + #areas = [{'text':item.name, 'id':item.id, 'name':'area'} for item in Area.objects.filter(translations__name__contains=term)] + + #countries = [{'text':item.name, 'id':item.id, 'name':'co'} for item in Country.objects.select_related('exposition_country')\ + # .filter(exposition_country__country__isnull=False, translations__language_code=lang, translations__name__contains=term).distinct()] + #cities = [{'text':item.name, 'id':item.id, 'name':'ci'} for item in City.objects.select_related('exposition_city')\ + # .filter(exposition_city__city__isnull=False, translations__language_code=lang, translations__name__contains=term).distinct()] + + #objects = areas + countries + cities + return HttpResponse(json.dumps(objects, indent=4), content_type='application/json') if form == 'subj': objects = [{'text': get_by_lang(item, 'name', lang), 'id':item.pk, 'name': item.form_name, 'cat': get_by_lang(item, 'parent', lang)} for item in SearchQuerySet().models(Theme, Tag).autocomplete(content_auto=term)] - return HttpResponse(json.dumps(objects), content_type='application/json') + return HttpResponse(json.dumps(objects, indent=4), content_type='application/json') else: return HttpResponse("Don't implemented yet") @@ -91,17 +95,20 @@ def expo_autosearch(request): if request.GET: lang = translation.get_language() term = request.GET['term'] + term = term.strip() d = datetime.date.today() expos = list(SearchQuerySet().models(Exposition).filter(data_end__gte=d).autocomplete(content_auto=term).order_by('data_begin','text')[:6]) - themes = list(SearchQuerySet().models(Tag).autocomplete(content_auto=term).order_by('text')[:15]) - res = expos + themes + confs = list(SearchQuerySet().models(Conference).filter(data_end__gte=d).autocomplete(content_auto=term).order_by('data_begin','text')[:6]) + tags = list(SearchQuerySet().models(Tag).autocomplete(content_auto=term).order_by('text')[:6]) + themes = list(SearchQuerySet().models(Theme).autocomplete(content_auto=term).order_by('text')[:6]) + res = expos + themes + tags + confs result = [{'cat': get_by_lang(item, 'catalog_name', lang), 'text': '%s (%s)'%(get_by_lang(item, 'name', lang),get_by_lang(item, 'parent', lang)) if get_by_lang(item, 'parent', lang) else get_by_lang(item, 'name', lang), 'url':item.url, 'id':item.pk, 'name': item.form_name} for item in res] result = sorted(result, key=lambda x:x['cat'], reverse=True) - return HttpResponse(json.dumps(result), content_type='application/json') + return HttpResponse(json.dumps(result, indent=4), content_type='application/json') else: raise Http404 diff --git a/static/custom_js/main.js b/static/custom_js/main.js index a4ae5a0a..7f2f0d3b 100644 --- a/static/custom_js/main.js +++ b/static/custom_js/main.js @@ -112,13 +112,13 @@ function postStat(data, textStatus){ $(document).ready(function(){ - +/* $('#id_created').datetimepicker({ todayHighlight: true, format : 'yyyy-mm-dd', minView:2 }); - +*/ $('#photo_form').on('submit', function(e){ e.preventDefault(); var url = $(this).attr('action'); diff --git a/templates/admin/base.html b/templates/admin/base.html index f2e998d3..a6b935ce 100644 --- a/templates/admin/base.html +++ b/templates/admin/base.html @@ -31,6 +31,10 @@ {# The fav icon #} +{# datetimepicker #} + + + {% block scripts %} {% endblock %} @@ -72,10 +76,7 @@ -{# datetimepicker #} - - - + {% block bot_scripts %} {% endblock %} \ No newline at end of file diff --git a/templates/admin/conference/conference.html b/templates/admin/conference/conference.html index 0201f346..51811f7f 100644 --- a/templates/admin/conference/conference.html +++ b/templates/admin/conference/conference.html @@ -181,6 +181,14 @@ {{ form.web_page.errors }} + {# organiser #} +
+ +
{{ form.org }} + {{ form.org.errors }} +
+
+ {# link #}
diff --git a/templates/admin/exposition/exposition.html b/templates/admin/exposition/exposition.html index 573c4950..a6953917 100644 --- a/templates/admin/exposition/exposition.html +++ b/templates/admin/exposition/exposition.html @@ -30,15 +30,8 @@ - -