diff --git a/city/forms.py b/city/forms.py index 01be8d49..c6aee5e0 100644 --- a/city/forms.py +++ b/city/forms.py @@ -9,7 +9,7 @@ from models import City from country.models import Country from directories.models import Iata #functions -from functions.translate import fill_trans_fields_all, populate_all +from functions.translate import fill_trans_fields_all, populate_all, fill_with_signal from functions.form_check import is_positive_integer, translit_with_separator from functions.files import check_tmp_files @@ -84,26 +84,16 @@ class CityForm(forms.Form): city.phone_code = data['phone_code'] city.population = data['population'] + if data.get('code_IATA'): city.code_IATA = Iata.objects.get(id=data['code_IATA'].id)#.id cause select uses queryset + if data.get('country'): city.country = Country.objects.get(id=data['country'].id)#.id cause select uses queryset - - # uses because in the next loop data will be overwritten + # url generate for city: "country_name-city_name" city.url = '%s-'%translit_with_separator(city.country.name) + translit_with_separator(data['name_ru']).lower() - city.save() - - - #will be saved populated fields - zero_fields = {} - #fills all translated fields with data - #if saves new object, will fill city object. otherwise existing object of City model - fill_trans_fields_all(City, city, data, id, zero_fields) - - #autopopulate - #populate empty fields and fields which was already populated - city_id = getattr(city, 'id') - populate_all(City, data, city_id, zero_fields) + # fill translated fields and save object + fill_with_signal(City, city, data) #save files check_tmp_files(city, data['key']) diff --git a/city/models.py b/city/models.py index 64db1de1..fcf0be06 100644 --- a/city/models.py +++ b/city/models.py @@ -91,5 +91,6 @@ def city_post_save_handler(sender, **kwargs): print('trans') if obj.language_code == 'ru': city = City.objects.get(id=obj.master_id) - city.url = translit_with_separator(obj.name) + country = city.country + city.url = '%s-%s'%(translit_with_separator(country.name), translit_with_separator(obj.name)) city.save() \ No newline at end of file diff --git a/country/forms.py b/country/forms.py index 1c075534..b79dd36a 100644 --- a/country/forms.py +++ b/country/forms.py @@ -8,7 +8,7 @@ from django.forms.util import ErrorList from models import Country, City from directories.models import Language, Currency, Iata #functions -from functions.translate import populate_all, fill_trans_fields_all +from functions.translate import fill_with_signal from functions.files import check_tmp_files from functions.form_check import is_positive_integer, translit_with_separator @@ -130,38 +130,6 @@ class CountryForm(forms.Form): country.language.clear() country.currency.clear() - all_langs = [code for code, lang in settings.LANGUAGES] - # fields in translations model that doesn't need - bad_fields = ['id', 'language_code', 'master_id'] - # translated fields - fields = [field.name for field in Country.translations.related.editable_fields() if field.name not in bad_fields] - - # translate to first language(require) - if not id: - country.translate(all_langs[0]) - # go through all fields and set value - for field in fields: - setattr(country, field, data.get('%s_%s'%(field, all_langs[0]))) - - # first save method call signal that fill require language to all translated fields - country.save() - else: - # require translation. uses for substitution unfilled form fields - require_transl = Country._meta.translations_model.objects.get(language_code = all_langs[0],master__id=getattr(country, 'id')) - - for code in all_langs[1:]: - # fill translation objects - # start from second language - obj = Country._meta.translations_model.objects.get(language_code = code,master__id=getattr(country, 'id')) - for field in fields: - val = data.get('%s_%s'%(field, code)) - if val == '': - # get value from require translation - setattr(obj, field, getattr(require_transl, field)) - else: - setattr(obj, field, val) - - obj.save() country.url = translit_with_separator(data['name_ru']).lower() country.population = data['population'] @@ -173,9 +141,8 @@ class CountryForm(forms.Form): if data.get('capital'): country.capital = City.objects.get(id=data['capital']) - - # uses because in the next loop data will be overwritten - country.save() + # fill translated fields and save object + fill_with_signal(Country, country, data) #fill manytomany fields for item in data['language']: @@ -187,10 +154,7 @@ class CountryForm(forms.Form): for item in data['currency']: country.currency.add(item.id)#.id cause select uses queryset - # uses because in the next loop data will be overwritten country.save() - - #save files check_tmp_files(country, data['key']) diff --git a/country/models.py b/country/models.py index d0711b86..3ac465eb 100644 --- a/country/models.py +++ b/country/models.py @@ -66,23 +66,11 @@ class Country(TranslatableModel): ) - """ - def __init__(self, **kwargs): - name = kwargs.get('name') - if name: - for code, language in settings.LANGUAGES: - self.translate(code) - self.name = name - else: - pass - """ - def __unicode__(self): return self.lazy_translation_getter('name', unicode(self.pk)) - -from django.db.models.signals import pre_save, post_save -#from models import Country +from django.db.models.signals import post_save +from models import Country from django.dispatch import receiver from django.conf import settings from functions.form_check import translit_with_separator @@ -90,7 +78,7 @@ from functions.form_check import translit_with_separator from functions.translate import get_translated_fields -@receiver(post_save) +@receiver(post_save, sender=Country) def country_post_save_handler(sender, **kwargs): """ objects saves two times: @@ -120,30 +108,10 @@ def country_post_save_handler(sender, **kwargs): setattr(obj, field, getattr(translation, field)) obj.save() - if isinstance(obj, CountryTranslation): # object is Translation + print('success') if obj.language_code == 'ru': country = Country.objects.get(id=obj.master_id) country.url = translit_with_separator(obj.name) - country.save() - #if not obj.url: - # obj.url = translit_with_separator(obj.name) - # obj.save() - """ - if kwargs['created']: - print(obj.name) - if not obj.url: - obj.url = translit_with_separator(obj.name) - obj.save() - """ - """ - 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() - """ - + country.save() \ No newline at end of file diff --git a/exposition/models.py b/exposition/models.py index 9b0f9a49..4f0589c8 100644 --- a/exposition/models.py +++ b/exposition/models.py @@ -171,4 +171,52 @@ class TimeTable(TranslatableModel): #translated fields translations = TranslatedFields( name = models.CharField(verbose_name='Название', max_length=255) - ) \ No newline at end of file + ) + + +from django.db.models.signals import post_save + +from django.dispatch import receiver +from django.conf import settings +from functions.form_check import translit_with_separator + +from functions.translate import get_translated_fields + +@receiver(post_save) +def exposition_post_save_handler(sender, **kwargs): + """ + objects saves two times: + - first time Exposition object + - second time ExpositionTranslation object + object must have at least one Translation + """ + + obj = kwargs['instance'] + if isinstance(obj, Exposition): + # object is Exposition + # what languages must be + all_langs = [code for code, lang in settings.LANGUAGES] + # what languages are + obj_langs = obj.get_available_languages() + # + missing_languages = list(set(all_langs) - set(obj_langs)) + # get first Translation object + translation = obj.translations.all()[0] + # + fields = get_translated_fields(obj) + for code in missing_languages: + # translate + obj.translate(code) + # go through all fields and set value + for field in fields: + setattr(obj, field, getattr(translation, field)) + + obj.save() + + if isinstance(obj, ExpositionTranslation): + # object is Translation + print('trans') + if obj.language_code == 'ru': + exp = Exposition.objects.get(id=obj.master_id) + exp.url = translit_with_separator(exp.name) + exp.save() \ No newline at end of file diff --git a/functions/translate.py b/functions/translate.py index 7a83e964..6a1a9285 100644 --- a/functions/translate.py +++ b/functions/translate.py @@ -91,6 +91,44 @@ def populate_all(Model, data={}, id=None, zero_fields={}): obj.save() +def fill_with_signal(model, obj, data): + all_langs = [code for code, lang in settings.LANGUAGES] + # fields in translations model that doesn't need + bad_fields = ['id', 'language_code', 'master_id'] + # translated fields + fields = [field.name for field in model.translations.related.editable_fields() if field.name not in bad_fields] + + # translate to first language(require) + if not obj.id: + # new object + # translate into first language + obj.translate(all_langs[0]) + # go through all fields and set value + for field in fields: + setattr(obj, field, data.get('%s_%s'%(field, all_langs[0]))) + + # first save method call signal that fill require language to all translated fields + obj.save() + + # require translation. uses for substitution unfilled form fields + require_transl = model._meta.translations_model.objects.get(language_code = all_langs[0],master__id=getattr(obj, 'id')) + + for code in all_langs[1:]: + # fill translation objects + # start from second language + trans_obj = model._meta.translations_model.objects.get(language_code = code,master__id=getattr(obj, 'id')) + for field in fields: + val = data.get('%s_%s'%(field, code)) + if val == '': + # get value from require translation + setattr(trans_obj, field, getattr(require_transl, field)) + else: + setattr(trans_obj, field, val) + + trans_obj.save() + + + def get_translated_fields(obj, exclude_fields=[]): """ get translated fields diff --git a/import_xls/excel_settings.py b/import_xls/excel_settings.py index ed6f5562..3a3b0161 100644 --- a/import_xls/excel_settings.py +++ b/import_xls/excel_settings.py @@ -59,6 +59,7 @@ field_settings = [ + def to_int(val): """ Reverse function to get_int @@ -81,7 +82,7 @@ def to_country(value): from city.models import City -def to_city(value, lang=None, country=None): +def to_city(value, lang, country): try: # get city by name objects = get_translation_aware_manager(City) @@ -91,18 +92,12 @@ def to_city(value, lang=None, country=None): except IndexError: # not found # try to create new city - city = City() + city = City(country=country) city.translate(lang) city.name = value city.save() - return city - - -AUDIENCE1 = ((None,'Не выбрано'), - ('experts', 'Специалисты'), - ('experts and consumers', 'Специалисты и потребители'), - ('general public', 'Широкая публика')) + return city def to_audience(value): try: @@ -113,40 +108,73 @@ def to_audience(value): elif value == 'Широкая публика': return 'general public' else: - return '' + return 'None' except: - return '' - - -def get_cell(field_name, value, lang=None): + return 'None' + +import_settings={ + 'name': {'func': str, }, + 'url': {'func': str}, + 'data_begin': {'func': str}, + 'data_end': {'func': str}, + 'main_title': {'func': str}, + 'description': {'func': str}, + 'audience': {'func': to_audience}, + 'country': {'func': to_country}, + 'city': {'func': to_city, 'extra_values': 'country'}, + 'periodic': {'func': str}, + 'web_page': {'func': str}, + 'time': {'func': str}, + 'products': {'func': str}, + 'foundation_year': {'func': to_int}, + 'tax': {'func': bool}, + 'currency': {'func': str}, + 'max_price': {'func': to_int}, + 'min_price': {'func': to_int}, + 'registration_payment': {'func': to_int}, + 'min_closed_area': {'func': to_int}, + 'max_closed_area': {'func': to_int}, + 'min_closed_equipped_area': {'func': to_int}, + 'max_closed)equipped_area': {'func': to_int}, + 'min_open_area': {'func': to_int}, + 'max_open_area': {'func': to_int}, + 'min_area': {'func': to_int}, + 'max_area': {'func': to_int}, + 'is_published': {'func': bool}, + 'canceled_by_administrator': {'func': bool} +} + +""" +def get_cell(field_name): 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, lang=lang), + 'url': str, + 'name': str, + 'data_begin': str, + 'data_end': str, + 'main_title': str, + 'description': str, + 'audience': to_audience, + 'country': to_country, + 'city': to_city, #'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) + 'web_page': str, + 'time': str, + 'products': str, + 'foundation_year': to_int, + 'tax': bool, + 'currency': str, + 'max_price': to_int, + 'min_price': to_int, + 'registration_payment': to_int, + 'min_closed_area': to_int, + 'max_closed_area': to_int, + 'min_closed_equipped_area': to_int, + 'max_closed_equipped_area': to_int, + 'min_open_area': to_int, + 'max_open_area': to_int, + 'min_area': to_int, + 'max_area': to_int, + 'is_published': bool, + 'canceled_by_administrator': bool }.get(field_name) +""" \ No newline at end of file diff --git a/import_xls/views.py b/import_xls/views.py index e4803f49..bb72c28d 100644 --- a/import_xls/views.py +++ b/import_xls/views.py @@ -9,45 +9,9 @@ import xlwt import xlrd # from custom_forms import ImportEventForm, ExportEventForm -from excel_settings import field_settings, get_cell - -""" -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'} - ] -""" - - +from excel_settings import field_settings, import_settings +relation_fields = ['city'] @login_required def import_event(request): args = {} @@ -57,6 +21,7 @@ def import_event(request): if request.POST: form = ImportEventForm(request.POST, request.FILES) if form.is_valid(): + lang = request.POST['language'] f = form.cleaned_data['excel_file'] book = xlrd.open_workbook(file_contents=f.read()) sheet = book.sheet_by_index(0) @@ -67,18 +32,49 @@ def import_event(request): # 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]) + # first two fields are verbose name and name + if row[0] != '': + object = model.objects.language(lang).get(id=row[0]) + else: + object = model() + object.translate(lang) for col_number, cell in enumerate(row): - value = get_cell(field_names[col_number], cell, request.POST['language']) - # - if not value: + field_name = field_names[col_number] + setting = import_settings.get(field_name) + if setting is not None: + # if setting exist for this field + func = setting.get('func') + if func is not None: + 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) + value = func(cell, lang, getattr(object, extra_value)) + else: + value = func(cell) + + setattr(object, field_name, value) + object.save() + + """ + func = get_cell(field_names[col_number]) + if not func: pass else: + if field_name in relation_fields: + value = func(cell, lang) + else: + value = func(cell) setattr(object, field_names[col_number], value) + """ - object.save() +# object.save() else: pass diff --git a/templates/admin/import templates/import_event.html b/templates/admin/import templates/import_event.html index 4e08217f..1acd078c 100644 --- a/templates/admin/import templates/import_event.html +++ b/templates/admin/import templates/import_event.html @@ -32,7 +32,14 @@ +
+

Поле id менять для редактирования старого события

+
+

Для создания нового события оставить поле id пустым

+
+

Город должен быть после страны, а тег после тематики

+