Set up signal which fills translated fields to some models. fixing problems with relation fields in import and export

remotes/origin/1203
Nazar Kotyuk 12 years ago
parent 1c04be5964
commit ac5aca4220
  1. 15
      conference/forms.py
  2. 44
      conference/models.py
  3. 16
      exposition/forms.py
  4. 17
      exposition/models.py
  5. 117
      import_xls/custom_forms.py
  6. 92
      import_xls/excel_settings.py
  7. 73
      import_xls/views.py
  8. 16
      seminar/forms.py
  9. 45
      seminar/models.py
  10. 27
      theme/forms.py
  11. 40
      theme/models.py
  12. 15
      webinar/forms.py
  13. 45
      webinar/models.py

@ -14,7 +14,7 @@ from company.models import Company
from service.models import Service
from place_conference.models import PlaceConference
#functions
from functions.translate import populate_all, fill_trans_fields_all
from functions.translate import populate_all, fill_trans_fields_all, fill_with_signal
from functions.form_check import is_positive_integer
from functions.files import check_tmp_files
from functions.form_check import translit_with_separator
@ -133,8 +133,7 @@ class ConferenceCreateForm(forms.Form):
if data.get('place'):
conference.place = PlaceConference.objects.get(id=data['place'].id)#.id cause select uses queryset
# uses because in the next loop data will be overwritten
conference.save()
fill_with_signal(Conference, conference, data)
#fill manytomany fields
for item in data['theme']:
conference.theme.add(item.id)#.id cause select uses queryset
@ -143,15 +142,7 @@ class ConferenceCreateForm(forms.Form):
conference.tag.add(item)
# uses because in the next loop data will be overwritten
conference.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(Conference, conference, data, id, zero_fields)
#autopopulate
#populate empty fields and fields which was already populated
conference_id = getattr(conference, 'id')
populate_all(Conference, data, conference_id, zero_fields)
#save files
check_tmp_files(conference, data['key'])

@ -158,4 +158,46 @@ class TimeTable(TranslatableModel):
#translated fields
translations = TranslatedFields(
name = models.CharField(verbose_name='Название', max_length=255)
)
)
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 conference_post_save_handler(sender, **kwargs):
"""
objects saves two times:
- first time Conference object
- second time ConferenceTranslation object
object must have at least one Translation
"""
obj = kwargs['instance']
if isinstance(obj, Conference):
# object is Exposition
if kwargs['created'] and obj.url == '':
# if url doesn't set in new object set it
obj.url = translit_with_separator(obj.name)
# 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]
# translated fields
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()

@ -15,7 +15,7 @@ from city.models import City
from service.models import Service
from place_exposition.models import PlaceExposition
#functions
from functions.translate import populate_all, fill_trans_fields_all
from functions.translate import populate_all, fill_trans_fields_all, fill_with_signal
from functions.form_check import is_positive_integer
from functions.files import check_tmp_files
from functions.form_check import translit_with_separator
@ -145,8 +145,9 @@ class ExpositionCreateForm(forms.Form):
if data.get('place'):
exposition.place = PlaceExposition.objects.get(id=data['place'].id)#.id cause select uses queryset
# uses because in the next loop data will be overwritten
exposition.save()
fill_with_signal(Exposition, exposition, data)
#fill manytomany fields
for item in data['theme']:
exposition.theme.add(item.id)#.id cause select uses queryset
@ -156,15 +157,6 @@ class ExpositionCreateForm(forms.Form):
# uses because in the next loop data will be overwritten
exposition.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(Exposition, exposition, data, id, zero_fields)
#autopopulate
#populate empty fields and fields which was already populated
exposition_id = getattr(exposition, 'id')
populate_all(Exposition, data, exposition_id, zero_fields)
#save files
check_tmp_files(exposition, data['key'])

@ -194,6 +194,10 @@ def exposition_post_save_handler(sender, **kwargs):
obj = kwargs['instance']
if isinstance(obj, Exposition):
# object is Exposition
if kwargs['created'] and obj.url == '':
# if url doesn't set in new object set it
obj.url = translit_with_separator(obj.name)
# what languages must be
all_langs = [code for code, lang in settings.LANGUAGES]
# what languages are
@ -202,8 +206,9 @@ def exposition_post_save_handler(sender, **kwargs):
missing_languages = list(set(all_langs) - set(obj_langs))
# get first Translation object
translation = obj.translations.all()[0]
#
# translated fields
fields = get_translated_fields(obj)
for code in missing_languages:
# translate
obj.translate(code)
@ -211,12 +216,4 @@ def exposition_post_save_handler(sender, **kwargs):
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()
obj.save()

@ -1,7 +1,11 @@
# -*- coding: utf-8 -*-
from django import forms
from django.conf import settings
from theme.models import Theme
from country.models import Country
from django.db.models.loading import get_model
import xlrd, xlwt
from excel_settings import import_settings, field_settings
languages = [code for code in settings.LANGUAGES]
@ -14,12 +18,58 @@ class ImportEventForm(forms.Form):
('webinar.Webinar', 'Вебинар')])
language = forms.ChoiceField(label='Выберите язык', choices=languages)
def save_events(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[1]]
# model
model = get_model(data['event'].split('.')[0], data['event'].split('.')[1])
for row_number, row in enumerate(row_list):
# go through all rows in file
if row_number > 1:
# first two fields are verbose name and name
if row[0] != '':
# in first column ids
object = model.objects.language(lang).get(id=row[0])
else:
# if id blank - its a new event
object = model()
object.translate(lang)
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
for col_number, cell in enumerate(row):
# go through row cells
# field name current cell
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()
class ExportEventForm(forms.Form):
@ -33,6 +83,61 @@ 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 export_events(self):
data = self.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
return None
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):
# 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)
if field['name']=='tag':
worksheet.write(row+2, col, field.get('type')(value, object.theme))
else:
worksheet.write(row+2, col, field.get('type')(value))
col += 1
return workbook
def clean_theme(self):
"""

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import xlwt
import datetime
from country.models import Country
from city.models import City
from theme.models import Theme, Tag
def get_bool(value):
if value:
@ -24,6 +25,25 @@ def get_audience(value):
else:
return ''
def get_theme(value):
objects = value.all()
return ', '.join(str(obj) for obj in objects)
def get_tag(tag, theme):
tags = tag.all()
themes = theme.all()
result = ''
for theme in themes:
# list of tags with current theme
tag_list = [str(tag) for tag in tags if tag.theme == theme]
result += '['+','.join(tag_list)+']'
return result
field_settings = [
{'name': 'id', 'verbose_name': 'id', 'type': get_int, 'width':1500},
{'name': 'url', 'verbose_name': 'url', 'type': str},
@ -35,6 +55,8 @@ field_settings = [
{'name': 'audience', 'verbose_name': 'Аудитория', 'type': get_audience},
{'name': 'country', 'verbose_name': 'Страна', 'type': str},
{'name': 'city', 'verbose_name': 'Город', 'type': str},
{'name': 'theme', 'verbose_name': 'Тематика', 'type': get_theme},
{'name': 'tag', 'verbose_name': 'Теги', 'type': get_tag},
{'name': 'periodic', 'verbose_name': 'Периодичность', 'type': str},
{'name': 'web_page', 'verbose_name': 'Веб страница', 'type': str},
{'name': 'time', 'verbose_name': 'Время проведения', 'type': str},
@ -70,7 +92,7 @@ def to_int(val):
except ValueError:
return None
from country.models import Country
from hvad.utils import get_translation_aware_manager
def to_country(value):
try:
@ -81,7 +103,7 @@ def to_country(value):
return None
from city.models import City
def to_city(value, lang, country):
try:
# get city by name
@ -112,6 +134,30 @@ def to_audience(value):
except:
return 'None'
def to_theme(value, lang='ru'):
theme_names = value.split(', ')
theme_objects = []
for name in theme_names:
try:
theme = Theme.objects.get(name=name)
except:
theme = Theme()
theme.translate(lang)
theme.name = name
theme.save()
theme_objects.append(theme)
return theme_objects
#def to_tag(value):
import_settings={
'name': {'func': str, },
'url': {'func': str},
@ -122,6 +168,7 @@ import_settings={
'audience': {'func': to_audience},
'country': {'func': to_country},
'city': {'func': to_city, 'extra_values': 'country'},
'theme': {'func': to_theme},
'periodic': {'func': str},
'web_page': {'func': str},
'time': {'func': str},
@ -142,39 +189,4 @@ import_settings={
'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,
'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,
'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)
"""
}

@ -18,72 +18,17 @@ def import_event(request):
form = ImportEventForm()
args.update(csrf(request))
args['form'] = form
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)
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):
if row_number > 1:
# 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):
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()
else:
pass
form.save_events()
args['message'] = 'Success'
return render_to_response('import_event.html', args)
return render_to_response('import_event.html', args)
@ -99,7 +44,12 @@ def export_event(request):
if request.POST:
form = ExportEventForm(request.POST)
if form.is_valid():
workbook = form.export_events()
if workbook is None:
pass
else:
return xls_to_response(workbook, 'My Worksheet.xls')
"""
data = form.cleaned_data
# get model
model = get_model(data['event'].split('.')[0], data['event'].split('.')[1])
@ -148,8 +98,9 @@ def export_event(request):
worksheet.write(row+2, col, field.get('type')(value))
col += 1
"""
return xls_to_response(workbook, 'My Worksheet.xls')
#return xls_to_response(workbook, 'My Worksheet.xls')
else:
form = ExportEventForm()

@ -14,7 +14,7 @@ from accounts.models import User
from company.models import Company
from service.models import Service
#functions
from functions.translate import populate_all, fill_trans_fields_all
from functions.translate import fill_with_signal
from functions.form_check import is_positive_integer
from functions.files import check_tmp_files
from functions.custom_fields import LocationWidget
@ -123,8 +123,7 @@ class SeminarCreateForm(forms.Form):
if data.get('city'):
seminar.city = City.objects.get(id=data['city'])
# uses because in the next loop data will be overwritten
seminar.save()
fill_with_signal(Seminar, seminar, data)
#fill manytomany fields
for item in data['theme']:
seminar.theme.add(item.id)#.id cause select uses queryset
@ -132,17 +131,8 @@ class SeminarCreateForm(forms.Form):
for item in data['tag']:
seminar.tag.add(item)
# uses because in the next loop data will be overwritten
seminar.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(Seminar, seminar, data, id, zero_fields)
#autopopulate
#populate empty fields and fields which was already populated
seminar_id = getattr(seminar, 'id')
populate_all(Seminar, data, seminar_id, zero_fields)
#save files
check_tmp_files(seminar, data['key'])

@ -139,4 +139,47 @@ class Seminar(TranslatableModel):
duplicate.save()
return duplicate
return duplicate
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 seminar_post_save_handler(sender, **kwargs):
"""
objects saves two times:
- first time Seminar object
- second time SeminarTranslation object
object must have at least one Translation
"""
obj = kwargs['instance']
if isinstance(obj, Seminar):
# object is Exposition
if kwargs['created'] and obj.url == '':
# if url doesn't set in new object set it
obj.url = translit_with_separator(obj.name)
# 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]
# translated fields
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()

@ -8,7 +8,7 @@ from bitfield.forms import BitFieldCheckboxSelectMultiple, BitFormField
from django.conf import settings
from ckeditor.widgets import CKEditorWidget
from functions.translate import fill_trans_fields, populate, ZERO_LANGUAGE, populate_all, fill_trans_fields_all
from functions.translate import fill_with_signal
@ -53,20 +53,10 @@ class ThemeForm(forms.Form):
flag = reduce(lambda x,y: x|y, (getattr(Theme.types, item) for item in data['types']))
theme.types = flag
# uses because in the next loop data will be overwritten
theme.save()
fill_with_signal(Theme, theme, data)
#populate fields with zero language
zero_fields = {}
fill_trans_fields_all(Theme, theme, data, id, zero_fields)
#autopopulate
#populate empty fields and fields which was already populated
theme_id = getattr(theme, 'id')
populate_all(Theme, data, theme_id, zero_fields)
def clean_types(self):
"""
@ -115,18 +105,7 @@ class TagForm(forms.Form):
if data.get('theme'):
tag.theme = Theme.objects.get(id=data['theme'])
# uses because in the next loop data will be overwritten
tag.save()
#populate fields with zero language
zero_fields = {}
fill_trans_fields_all(Tag, tag, data, id, zero_fields)
#autopopulate
#populate empty fields and fields which was already populated
tag_id = getattr(tag, 'id')
populate_all(Tag, data, tag_id, zero_fields)
fill_with_signal(Tag, tag, data)
class ThemeDeleteForm(forms.ModelForm):

@ -149,4 +149,42 @@ class Tag(TranslatableModel):
duplicate.save()
return duplicate
return duplicate
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from functions.translate import get_translated_fields
@receiver(post_save)
def theme_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, Theme) or isinstance(obj, Tag):
# object is Theme or Tag
# 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]
# translated fields
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()

@ -16,7 +16,7 @@ from functions.form_check import translit_with_separator
#functions
from functions.translate import populate_all, fill_trans_fields_all
from functions.translate import fill_with_signal
from functions.form_check import is_positive_integer
class WebinarCreateForm(forms.Form):
@ -108,8 +108,7 @@ class WebinarCreateForm(forms.Form):
webinar.tax = data['tax']
webinar.min_price = data['min_price']
webinar.max_price = data['max_price']
# uses because in the next loop data will be overwritten
webinar.save()
fill_with_signal(Webinar, webinar, data)
#fill manytomany fields
for item in data['theme']:
webinar.theme.add(item)
@ -119,15 +118,7 @@ class WebinarCreateForm(forms.Form):
# uses because in the next loop data will be overwritten
webinar.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(Webinar, webinar, data, id, zero_fields)
#autopopulate
#populate empty fields and fields which was already populated
webinar_id = getattr(webinar, 'id')
populate_all(Webinar, data, webinar_id, zero_fields)
#save files
check_tmp_files(webinar, data['key'])

@ -136,4 +136,47 @@ class Webinar(TranslatableModel):
duplicate.save()
return duplicate
return duplicate
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 webinar_post_save_handler(sender, **kwargs):
"""
objects saves two times:
- first time Webinar object
- second time WebinarTranslation object
object must have at least one Translation
"""
obj = kwargs['instance']
if isinstance(obj, Webinar):
# object is Exposition
if kwargs['created'] and obj.url == '':
# if url doesn't set in new object set it
obj.url = translit_with_separator(obj.name)
# 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]
# translated fields
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()
Loading…
Cancel
Save