owerwrite all

remotes/origin/1203
Nazar Kotyuk 12 years ago
parent 11cccfafdc
commit 9f520b7140
  1. 6
      accounts/admin_urls.py
  2. 4
      accounts/forms.py
  3. 36
      accounts/models.py
  4. 14
      accounts/search_indexes.py
  5. 20
      article/models.py
  6. 2
      article/signals.py
  7. 1
      city/admin.py
  8. 28
      city/forms.py
  9. 39
      city/models.py
  10. 5
      city/signals.py
  11. 13
      company/forms.py
  12. 64
      company/models.py
  13. 2
      company/signals.py
  14. 10
      company/urls.py
  15. 22
      company/views.py
  16. 56
      conference/admin.py
  17. 108
      conference/forms.py
  18. 100
      conference/models.py
  19. 2
      conference/signals.py
  20. 15
      conference/urls.py
  21. 70
      conference/views.py
  22. 0
      core/__init__.py
  23. 3
      core/models.py
  24. 16
      core/tests.py
  25. 77
      core/views.py
  26. 16
      country/admin.py
  27. 20
      country/forms.py
  28. 36
      country/models.py
  29. 8
      country/signals.py
  30. 99
      exposition/admin.py
  31. 262
      exposition/forms.py
  32. 215
      exposition/models.py
  33. 15
      exposition/search_indexes.py
  34. 2
      exposition/signals.py
  35. 18
      exposition/urls.py
  36. 118
      exposition/views.py
  37. 2
      file/forms.py
  38. 2
      file/models.py
  39. 4
      functions/__init__.py
  40. 3
      functions/custom_fields.py
  41. 156
      functions/custom_views.py
  42. 30
      functions/files.py
  43. 2
      functions/form_check.py
  44. 18
      functions/forms.py
  45. 61
      functions/model_mixin.py
  46. 27
      functions/models_methods.py
  47. 9
      functions/signal_additional_func.py
  48. 42
      functions/signal_handlers.py
  49. 13
      functions/views_help.py
  50. 111
      import_xls/admin.py
  51. 25
      import_xls/admin_urls.py
  52. 221
      import_xls/excel_settings.py
  53. 172
      import_xls/export_forms.py
  54. 237
      import_xls/import_forms.py
  55. 64
      import_xls/views.py
  56. BIN
      media/imgs/.jpg
  57. BIN
      media/imgs/cl-logo-1.png
  58. BIN
      media/imgs/cl-logo-1_1.png
  59. BIN
      media/imgs/cl-logo-1_2.png
  60. BIN
      media/imgs/cl-logo-1_3.png
  61. BIN
      media/imgs/cl-logo-1_4.png
  62. BIN
      media/imgs/cl-logo-1_5.png
  63. BIN
      media/imgs/cl-logo-2.png
  64. BIN
      media/imgs/cl-logo-2_1.1.png
  65. BIN
      media/imgs/cl-logo-2_1.png
  66. BIN
      media/imgs/cl-logo-3.png
  67. BIN
      media/imgs/cl-logo-3_5.1.png
  68. BIN
      media/imgs/cl-logo-3_5.2.png
  69. BIN
      media/imgs/cl-logo-3_5.png
  70. BIN
      media/imgs/mp-phg-1.png
  71. BIN
      media/imgs/part-logo-1.png
  72. BIN
      media/imgs/part-logo-1_1.png
  73. BIN
      media/imgs/pl-logo-2.png
  74. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-cool.gif
  75. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-cry.gif
  76. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-embarassed.gif
  77. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-foot-in-mouth.gif
  78. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-frown.gif
  79. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-innocent.gif
  80. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-kiss.gif
  81. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-laughing.gif
  82. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-money-mouth.gif
  83. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-sealed.gif
  84. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-smile.gif
  85. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-surprised.gif
  86. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-tongue-out.gif
  87. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-undecided.gif
  88. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-wink.gif
  89. BIN
      media/js/tiny_mce/plugins/emoticons/img/smiley-yell.gif
  90. BIN
      media/js/tiny_mce/skins/lightgray/img/anchor.gif
  91. BIN
      media/js/tiny_mce/skins/lightgray/img/loader.gif
  92. BIN
      media/js/tiny_mce/skins/lightgray/img/object.gif
  93. BIN
      media/js/tiny_mce/skins/lightgray/img/trans.gif
  94. BIN
      media/js/tiny_mce/skins/lightgray/img/wline.gif
  95. BIN
      media/tmp_files/.jpg
  96. BIN
      media/tmp_files/cl-logo-1.png
  97. BIN
      media/tmp_files/cl-logo-1_1.png
  98. BIN
      media/tmp_files/cl-logo-1_2.png
  99. BIN
      media/tmp_files/cl-logo-2.png
  100. BIN
      media/tmp_files/cl-logo-3.png
  101. Some files were not shown because too many files have changed in this diff Show More

@ -2,9 +2,9 @@
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^registration/$', 'accounts.admin.registration'), #url(r'^registration/$', 'accounts.admin.registration'),
url(r'^create_admin/$', 'accounts.admin.create_admin'), #url(r'^create_admin/$', 'accounts.admin.create_admin'),
url(r'^create_md5user/$', 'accounts.admin.create_md5'), #url(r'^create_md5user/$', 'accounts.admin.create_md5'),
url(r'^change/(.*)/$', 'accounts.admin.user_change'), url(r'^change/(.*)/$', 'accounts.admin.user_change'),
# url(r'^change/(?P<user_id>\d+).*/$', 'accounts.views.user_change'), # url(r'^change/(?P<user_id>\d+).*/$', 'accounts.views.user_change'),
url(r'^all/$', 'accounts.admin.user_all'), url(r'^all/$', 'accounts.admin.user_all'),

@ -58,7 +58,7 @@ class UserChangeForm(forms.ModelForm):
return self.initial['password'] return self.initial['password']
class UserForm(forms.ModelForm): class UserForm(forms.ModelForm):
email = forms.EmailField(widget=forms.TextInput(attrs={'disabled' : True})) email = forms.EmailField(widget=forms.TextInput(attrs={'disabled' : True}), required=False)
country = forms.ModelChoiceField(label='Страна', queryset=Country.objects.all(), empty_label=None, required=False) country = forms.ModelChoiceField(label='Страна', queryset=Country.objects.all(), empty_label=None, required=False)
city = forms.ModelChoiceField(label='Город', queryset=City.objects.all(), empty_label='', required=False) city = forms.ModelChoiceField(label='Город', queryset=City.objects.all(), empty_label='', required=False)
company = forms.ModelChoiceField(label='Компания', queryset=Company.objects.all(), empty_label='', required=False) company = forms.ModelChoiceField(label='Компания', queryset=Company.objects.all(), empty_label='', required=False)
@ -153,7 +153,7 @@ class ChangePasswordForm(forms.Form):
return data return data
class EmailAnnouncementForm(forms.Form): class EmailAnnouncementForm(forms.Form):
data = [(1, _(u'Получать приглашения, сообщения и другю корреспонденцию от пользователей Expomap')), data = [(1, _(u'Получать приглашения, сообщения и другую корреспонденцию от пользователей Expomap')),
(2, _(u'Получать обзор событий')), (2, _(u'Получать обзор событий')),
(3, _(u'Получать новости'))] (3, _(u'Получать новости'))]
announcement = forms.MultipleChoiceField(choices=data, widget=forms.CheckboxSelectMultiple()) announcement = forms.MultipleChoiceField(choices=data, widget=forms.CheckboxSelectMultiple())

@ -4,10 +4,11 @@ from hvad.models import TranslatableModel, TranslatedFields
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin
from django.core.mail import send_mail from django.core.mail import send_mail
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext as _
from django.db.models.signals import post_save from django.db.models.signals import post_save
#custom functions #custom functions
from functions.form_check import translit_with_separator from functions.form_check import translit_with_separator
from functions.translate import fill_trans_fields_all, populate_all
""" """
from django.contrib.auth.hashers import check_password from django.contrib.auth.hashers import check_password
@ -70,7 +71,7 @@ class User(AbstractBaseUser, PermissionsMixin):
""" """
email = models.EmailField( email = models.EmailField(
verbose_name = 'Электронная почта', verbose_name = u'Электронная почта',
max_length = 255, max_length = 255,
unique = True, unique = True,
db_index = True, db_index = True,
@ -100,15 +101,16 @@ class User(AbstractBaseUser, PermissionsMixin):
on_delete=models.PROTECT) on_delete=models.PROTECT)
company = models.ForeignKey('company.Company', blank=True, null=True, on_delete=models.PROTECT, related_name='users') company = models.ForeignKey('company.Company', blank=True, null=True, on_delete=models.PROTECT, related_name='users')
#other user information
phone = models.PositiveIntegerField(verbose_name='Телефон', blank=True, null=True) # other user information
phone = models.BigIntegerField(verbose_name='Телефон', blank=True, null=True)
position = models.CharField(verbose_name='Должность', max_length=255, blank=True) position = models.CharField(verbose_name='Должность', max_length=255, blank=True)
about = models.TextField(verbose_name='О себе', blank=True) about = models.TextField(verbose_name='О себе', blank=True)
avatar = models.ImageField(verbose_name='Фото', upload_to='/accounts/avatar/', blank=True) avatar = models.ImageField(verbose_name='Фото', upload_to='/accounts/avatar/', blank=True)
web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True) web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True)
social = models.TextField(verbose_name='Социальные страници', blank=True) social = models.TextField(verbose_name='Социальные страницы', blank=True)
skype = models.CharField(blank=True, max_length=50) skype = models.CharField(blank=True, max_length=50)
#meta # meta
title = models.CharField(max_length=255, blank=True) title = models.CharField(max_length=255, blank=True)
descriptions = models.CharField(max_length=255, blank=True) descriptions = models.CharField(max_length=255, blank=True)
keywords = models.CharField(max_length=255, blank=True) keywords = models.CharField(max_length=255, blank=True)
@ -149,6 +151,28 @@ class User(AbstractBaseUser, PermissionsMixin):
def has_module_perms(self, app_label): def has_module_perms(self, app_label):
return True return True
def get_events_number(self):
expositions = self.exposition_users.all()
conferences = self.conference_users.all()
seminars = self.seminar_users.all()
webinars = self.webinar_users.all()
return len(list(expositions)+list(conferences)+list(seminars)+list(webinars))
class Calendar(models.Model):
user = models.OneToOneField(User)
expositions = models.ManyToManyField('exposition.Exposition', null=True)
conferences = models.ManyToManyField('conference.Conference', null=True)
seminars = models.ManyToManyField('seminar.Seminar', null=True)
webinars = models.ManyToManyField('webinar.Webinar', null=True)
def create_user_calendar(sender, instance, created, **kwargs):
if created:
Calendar.objects.create(user=instance)
post_save.connect(create_user_calendar, sender=User)
#need import after User Model, because User imported in "organiser.models" #need import after User Model, because User imported in "organiser.models"
from organiser.models import Organiser from organiser.models import Organiser

@ -0,0 +1,14 @@
from haystack import indexes
from models import User
class UserIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
first_name = indexes.CharField(model_attr='first_name')
def get_model(self):
return User
def index_queryset(self, using=None):
return self.get_model().objects.all()

@ -58,9 +58,19 @@ class Article(TranslatableModel):
#already has copy this instance #already has copy this instance
return return
ignore_fields = ['id', 'master', 'language_code']
duplicate.translate('ru')
tr = self._meta.translations_model.objects.get(language_code = 'ru',master__id=self.pk)
for field in duplicate._translated_field_names:
if field in ignore_fields:
continue
setattr(duplicate, field, getattr(tr, field))
duplicate.save() duplicate.save()
# but lost all ManyToMany relations and Translations. # but lost all ManyToMany relations and Translations.
'''
# copy relations # copy relations
for field in self._meta.many_to_many: for field in self._meta.many_to_many:
source = getattr(self, field.attname) source = getattr(self, field.attname)
@ -83,5 +93,11 @@ class Article(TranslatableModel):
setattr(duplicate, field, getattr(tr, field)) setattr(duplicate, field, getattr(tr, field))
duplicate.save() duplicate.save()
'''
return duplicate
from django.db.models.signals import post_save
from functions.signal_handlers import post_save_handler
return duplicate post_save.connect(post_save_handler, sender=Article)

@ -3,4 +3,4 @@ from django.db.models.signals import post_save
from models import Article from models import Article
from functions.signal_handlers import post_save_handler from functions.signal_handlers import post_save_handler
post_save.connect(post_save_handler, sender=Article) #post_save.connect(post_save_handler, sender=Article)

@ -67,6 +67,7 @@ def city_change(request, url):
for code, name in settings.LANGUAGES: for code, name in settings.LANGUAGES:
obj = City._meta.translations_model.objects.get(language_code = code,master__id=city_id) #access to translated fields obj = City._meta.translations_model.objects.get(language_code = code,master__id=city_id) #access to translated fields
data['name_%s' % code] = obj.name data['name_%s' % code] = obj.name
data['region_%s' % code] = obj.region
data['description_%s' % code] = obj.description data['description_%s' % code] = obj.description
data['famous_places_%s' % code] = obj.famous_places data['famous_places_%s' % code] = obj.famous_places
data['shoping_%s' % code] = obj.shoping data['shoping_%s' % code] = obj.shoping

@ -4,6 +4,7 @@ from django.conf import settings
from ckeditor.widgets import CKEditorWidget from ckeditor.widgets import CKEditorWidget
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms.util import ErrorList from django.forms.util import ErrorList
from django.utils.translation import get_language as lang
#models #models
from models import City from models import City
from country.models import Country from country.models import Country
@ -23,13 +24,14 @@ class CityForm(forms.Form):
save function saves data in City object. If it doesnt exist create new object save function saves data in City object. If it doesnt exist create new object
""" """
country = forms.ModelChoiceField(label='Страна', queryset=Country.objects.all(), empty_label=None) country = forms.ModelChoiceField(label='Страна',
queryset=Country.objects.filter(translations__language_code=lang()).order_by('translations__name'),
empty_label=None)
population = forms.CharField(label='Население', required=False, population = forms.CharField(label='Население', required=False,
widget=forms.TextInput(attrs={'placeholder':'Население'})) widget=forms.TextInput(attrs={'placeholder':'Население'}))
phone_code = forms.CharField(label='Код города', required=False, phone_code = forms.CharField(label='Код города', required=False,
widget=forms.TextInput(attrs={'placeholder':'Код города'})) widget=forms.TextInput(attrs={'placeholder':'Код города'}))
code_IATA = forms.ModelChoiceField(label='Код IATA', queryset=Iata.objects.all(), empty_label=None, required=False) code_IATA = forms.ModelChoiceField(label='Код IATA', queryset=Iata.objects.all(), empty_label=None, required=False)
country = forms.ModelChoiceField(label='Страна', queryset=Country.objects.all(), empty_label=None)
#field for comparing tmp files #field for comparing tmp files
key = forms.CharField(required=False, widget=forms.HiddenInput()) key = forms.CharField(required=False, widget=forms.HiddenInput())
# #
@ -49,6 +51,7 @@ class CityForm(forms.Form):
# first iteration is a default lang so it required fields # first iteration is a default lang so it required fields
required = True if lid == 0 else False required = True if lid == 0 else False
self.fields['name_%s' % code] = forms.CharField(label='Название', required=required) self.fields['name_%s' % code] = forms.CharField(label='Название', required=required)
self.fields['region_%s' % code] = forms.CharField(label='Регион', required=False)
self.fields['description_%s' % code] = forms.CharField(label='Описание', self.fields['description_%s' % code] = forms.CharField(label='Описание',
required=False, widget=CKEditorWidget) required=False, widget=CKEditorWidget)
self.fields['famous_places_%s' % code] = forms.CharField(label='Знаменитые места', self.fields['famous_places_%s' % code] = forms.CharField(label='Знаменитые места',
@ -79,20 +82,28 @@ class CityForm(forms.Form):
else: else:
city = City() city = City()
city.phone_code = data.get('phone_code') city.phone_code = data['phone_code']
city.population = data.get('population') city.population = data.get('population')
if data.get('code_IATA'): if data.get('code_IATA'):
city.code_IATA = Iata.objects.get(id=data['code_IATA'].id)# .id cause select uses queryset city.code_IATA = Iata.objects.get(id=data['code_IATA'].id)# .id cause select uses queryset
if data.get('country'): if data.get('country'):
city.country = Country.objects.get(id=data['country'].id)# .id cause select uses queryset city.country = data['country']# .id cause select uses queryset
#city.country = Country.objects.get(id=data['country'].id)# .id cause select uses queryset
# url generate for city: "country_name-city_name" # url generate for city: "country_name-city_name"
city.url = '%s-'%translit_with_separator(city.country.name) + translit_with_separator(data['name_ru']).lower() if data.get('name_en'):
city.url = '%s-'%translit_with_separator(city.country.name) + translit_with_separator(data['name_en']).lower()
else:
city.url = '%s-'%translit_with_separator(city.country.name) + translit_with_separator(data['name_ru']).lower()
#city.url = '%s'%translit_with_separator(data['name_ru'].strip()).lower()
#city.save()
# fill translated fields and save object # fill translated fields and save object
fill_with_signal(City, city, data) fill_with_signal(City, city, data)
city.save()
# save files # save files
check_tmp_files(city, data['key']) check_tmp_files(city, data['key'])
@ -100,11 +111,16 @@ class CityForm(forms.Form):
def clean(self): def clean(self):
id = self.cleaned_data.get('city_id') id = self.cleaned_data.get('city_id')
name_ru = self.cleaned_data.get('name_ru') name_ru = self.cleaned_data.get('name_ru')
name_en = self.cleaned_data.get('name_en')
country = self.cleaned_data.get('country') country = self.cleaned_data.get('country')
city = City.objects.filter( city = City.objects.filter(
url='%s-%s'%(translit_with_separator(country.name), translit_with_separator(name_ru)) url='%s-%s'%(translit_with_separator(country.name), translit_with_separator(name_en))
) )
if not city:
city = City.objects.filter(
url='%s-%s'%(translit_with_separator(country.name), translit_with_separator(name_ru))
)
if city and str(city[0].id) != id: if city and str(city[0].id) != id:
msg = 'Город с таким названием уже существует' msg = 'Город с таким названием уже существует'
self._errors['name_ru'] = ErrorList([msg]) self._errors['name_ru'] = ErrorList([msg])

@ -1,22 +1,22 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
from django.db.models.signals import post_save, pre_save from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from hvad.models import TranslatableModel, TranslatedFields
from bitfield import BitField from bitfield import BitField
# my models # models
from directories.models import Iata from directories.models import Iata
from service.models import Service from service.models import Service
from settings.models import Setting # custom functions
# custom dunctions
from functions.db import db_table_exists from functions.db import db_table_exists
from functions.form_check import translit_with_separator from functions.signal_handlers import post_save_handler
from functions.signal_additional_func import fill_missing_languages, fill_meta_information from functions.models_methods import ExpoManager
#check if table exist and create flags if true #check if table exist and create flags if true
flags = [str(item.id) for item in Service.objects.all()] if db_table_exists('service_service') else [] flags = [str(item.id) for item in Service.objects.all()] if db_table_exists('service_service') else []
class City(TranslatableModel): class City(TranslatableModel):
""" """
Create City model Create City model
@ -24,6 +24,7 @@ class City(TranslatableModel):
Uses hvad.TranslatableModel which is child of django.db.models class Uses hvad.TranslatableModel which is child of django.db.models class
""" """
objects = ExpoManager()
services = BitField(flags=flags) services = BitField(flags=flags)
@ -37,6 +38,7 @@ class City(TranslatableModel):
#translated fields #translated fields
translations = TranslatedFields( translations = TranslatedFields(
name = models.CharField(max_length=50), name = models.CharField(max_length=50),
region = models.CharField(max_length=255),
transport = models.TextField(blank=True), transport = models.TextField(blank=True),
description = models.TextField(blank=True), description = models.TextField(blank=True),
famous_places = models.TextField(blank=True), famous_places = models.TextField(blank=True),
@ -54,25 +56,6 @@ class City(TranslatableModel):
return self.lazy_translation_getter('name', self.pk) return self.lazy_translation_getter('name', self.pk)
@receiver(post_save)
def city_post_save_handler(sender, **kwargs):
"""
objects saves two times:
- first time Country object
- second time CountryTranslation object
object must have at least one Translation
"""
obj = kwargs['instance']
if isinstance(obj, City): post_save.connect(post_save_handler, sender=City)
fill_missing_languages(obj)
fill_meta_information(obj)
"""
if isinstance(obj, CityTranslation):
# object is Translation - set url
if obj.language_code == 'ru':
city = City.objects.get(id=obj.master_id)
country = city.country
city.url = '%s-%s'%(translit_with_separator(country.name), translit_with_separator(obj.name))
city.save()
"""

@ -1,8 +1,3 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db.models.signals import post_save
from models import City
from functions.signal_handlers import post_save_handler
post_save.connect(post_save_handler, sender=City)

@ -4,6 +4,7 @@ from django.conf import settings
from ckeditor.widgets import CKEditorWidget from ckeditor.widgets import CKEditorWidget
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms.util import ErrorList from django.forms.util import ErrorList
from django.core.validators import validate_email, URLValidator
#models #models
from models import Company from models import Company
from country.models import Country from country.models import Country
@ -155,14 +156,14 @@ class CompanyForm(forms.Form):
cleaned_data = super(CompanyForm, self).clean() cleaned_data = super(CompanyForm, self).clean()
web_page = cleaned_data.get('web_page') web_page = cleaned_data.get('web_page')
if not web_page: if not web_page:
return web_page return ''
import socket validate = URLValidator()
try: try:
socket.getaddrinfo(web_page, 80) validate(web_page)
return web_page except(ValidationError),e:
except: raise ValidationError(e.messages[0])
return forms.ValidationError('Введите правильный адрес страници') return web_page
def clean_phone(self): def clean_phone(self):
""" """

@ -1,31 +1,29 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from django.contrib.contenttypes import generic
# #
from functions.custom_fields import LocationField from functions.custom_fields import LocationField
from functions.models_methods import ExpoManager
from functions.model_mixin import ExpoMixin
class CompanyManager(TranslationManager):
def safe_get(self, **kwargs):
model = self.model
try:
return model.objects.get(**kwargs)
except:
return None
class Company(TranslatableModel): class Company(TranslatableModel, ExpoMixin):
""" """
Create Company model Create Company model
Uses hvad.TranslatableModel which is child of django.db.models class Uses hvad.TranslatableModel which is child of django.db.models class
""" """
objects = CompanyManager() objects = ExpoManager()
files = generic.GenericRelation('file.FileModel', content_type_field='content_type', object_id_field='object_id')
url = models.SlugField() url = models.SlugField()
#relations #relations
creator = models.ForeignKey('accounts.User', verbose_name='Создатель', related_name='created_company') creator = models.ForeignKey('accounts.User', verbose_name='Создатель', related_name='created_company',
blank=True, null=True)
theme = models.ManyToManyField('theme.Theme', verbose_name='Отрасль', theme = models.ManyToManyField('theme.Theme', verbose_name='Отрасль',
blank=True, null=True, related_name='companies') blank=True, null=True, related_name='companies')
tag = models.ManyToManyField('theme.Tag', verbose_name='Теги', blank=True, null=True, related_name='companies') tag = models.ManyToManyField('theme.Tag', verbose_name='Теги', blank=True, null=True, related_name='companies')
@ -37,14 +35,14 @@ class Company(TranslatableModel):
address = LocationField(verbose_name='Адрес', blank=True) address = LocationField(verbose_name='Адрес', blank=True)
staff_number = models.CharField(verbose_name='Количество сотрудников', max_length=50, blank=True) staff_number = models.CharField(verbose_name='Количество сотрудников', max_length=50, blank=True)
phone = models.FloatField(verbose_name='Телефон', blank=True, null=True) phone = models.BigIntegerField(verbose_name='Телефон', blank=True, null=True)
fax = models.FloatField(verbose_name='Факс', blank=True, null=True) fax = models.BigIntegerField(verbose_name='Факс', blank=True, null=True)
web_page = models.CharField(verbose_name='Веб-сайт',max_length=255, blank=True) web_page = models.CharField(verbose_name='Веб-сайт',max_length=255, blank=True)
email = models.EmailField(verbose_name='Email', blank=True) email = models.EmailField(verbose_name='Email', blank=True)
social = models.TextField(verbose_name='Социальные страници', blank=True) social = models.TextField(verbose_name='Социальные страници', blank=True)
foundation = models.PositiveIntegerField(verbose_name='Год основания', blank=True, null=True) foundation = models.PositiveIntegerField(verbose_name='Год основания', blank=True, null=True)
#translation fields #translation fields
translation = TranslatedFields( translations = TranslatedFields(
name = models.CharField(verbose_name='Название компании', max_length=255), name = models.CharField(verbose_name='Название компании', max_length=255),
specialization = models.CharField(verbose_name='Специализация', max_length=255, blank=True), specialization = models.CharField(verbose_name='Специализация', max_length=255, blank=True),
description = models.TextField(verbose_name='О компании', blank=True), description = models.TextField(verbose_name='О компании', blank=True),
@ -60,4 +58,42 @@ class Company(TranslatableModel):
def __unicode__(self): def __unicode__(self):
return self.lazy_translation_getter('name', self.pk) return self.lazy_translation_getter('name', self.pk)
def get_catalog_url(self):
return '/members/'
def get_permanent_url(self):
url = '%smember-%s'%(self.get_catalog_url(), self.url)
return url
def get_expositions_number(self):
return len(self.exposition_companies.all())
def get_conferences_number(self):
return len(self.conference_companies.all())
def get_seminars_number(self):
return len(self.seminar_companies.all())
def get_webinars_number(self):
return len(self.webinar_companies.all())
def get_events_number(self):
expositions = self.exposition_companies.all()
conferences = self.conference_companies.all()
seminars = self.seminar_companies.all()
webinars = self.webinar_companies.all()
return len(list(expositions)+list(conferences)+list(seminars)+list(webinars))
def get_events(self):
expositions = self.exposition_companies.all()
conferences = self.conference_companies.all()
seminars = self.seminar_companies.all()
webinars = self.webinar_companies.all()
return list(expositions)+ list(conferences)+list(seminars)+list(webinars)
from django.db.models.signals import post_save
from functions.signal_handlers import post_save_handler
post_save.connect(post_save_handler, sender=Company)

@ -3,4 +3,4 @@ from django.db.models.signals import post_save
from models import Company from models import Company
from functions.signal_handlers import post_save_handler from functions.signal_handlers import post_save_handler
post_save.connect(post_save_handler, sender=Company) #post_save.connect(post_save_handler, sender=Company)

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from views import CompanyView
urlpatterns = patterns('',
url(r'members/(?P<params>.*)/(?P<page>\d+)/$', CompanyView.as_view()),
url(r'members/(?P<page>\d+)/$', CompanyView.as_view()),
url(r'members/(?P<params>.*)/$', CompanyView.as_view()),
url(r'members/$', CompanyView.as_view()),
)

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from models import Company
from functions.custom_views import ExpoListView
import json
class CompanyView(ExpoListView):
model = Company
template_name = 'company_catalog.html'
class CompanyExposition(CompanyView):
template_name = 'test_list.html'
def get_queryset(self):
params = self.get_params()
for param in params:
if param.get('type') == 'event':
company = Company.objects.safe_get(url=param.get('url'))
#query = exp.users
self.params = params
return company.exposition_companies.all()

@ -8,8 +8,8 @@ from django.forms.models import modelformset_factory
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
#models and forms #models and forms
from models import Conference, TimeTable from models import Conference, TimeTable, Statistic
from forms import ConferenceChangeForm, ConferenceCreateForm, ConferenceDeleteForm, TimeTableForm from forms import ConferenceChangeForm, ConferenceCreateForm, ConferenceDeleteForm, TimeTableForm, StatisticForm
from theme.models import Tag from theme.models import Tag
from city.models import City from city.models import City
from file.models import FileModel, TmpFile from file.models import FileModel, TmpFile
@ -72,6 +72,8 @@ def conference_add(request):
If form is posted redirect on the page of all conferences. If form is posted redirect on the page of all conferences.
""" """
# formset of StatisticForm
StatisticFormSet = formset_factory(StatisticForm)
#if form would be not valid key must be same #if form would be not valid key must be same
if request.POST.get('key'): if request.POST.get('key'):
key = request.POST['key'] key = request.POST['key']
@ -85,12 +87,20 @@ def conference_add(request):
#set choices filled by ajax #set choices filled by ajax
form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()] form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()]
form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=request.POST['country'])] form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=request.POST['country'])]
#
if form.is_valid(): formset_statistic = StatisticFormSet(request.POST)
form.save() if form.is_valid() and formset_statistic.is_valid():
conference = form.save()
for item in formset_statistic.forms:
#saves forms if its valid and not empty
if item.is_valid() and item.has_changed():
statistic = item.save(commit=False)
statistic.conference = conference
statistic.save()
return HttpResponseRedirect('/admin/conference/all/') return HttpResponseRedirect('/admin/conference/all/')
else: else:
form = ConferenceCreateForm(initial={'key': key}) form = ConferenceCreateForm(initial={'key': key})
formset_statistic = StatisticFormSet()
args = {} args = {}
args.update(csrf(request)) args.update(csrf(request))
@ -99,6 +109,7 @@ def conference_add(request):
args['languages'] = settings.LANGUAGES args['languages'] = settings.LANGUAGES
args['file_form'] = file_form args['file_form'] = file_form
args['files'] = TmpFile.objects.filter(key=key) args['files'] = TmpFile.objects.filter(key=key)
args['formset_statistic'] = formset_statistic
return render_to_response('conference_add.html', args) return render_to_response('conference_add.html', args)
@ -123,20 +134,36 @@ def conference_change(request, url):
return HttpResponseRedirect('/admin/conference/all/') return HttpResponseRedirect('/admin/conference/all/')
if request.POST: if request.POST:
StatisticFormSet = formset_factory(StatisticForm)
form = ConferenceChangeForm(request.POST) form = ConferenceChangeForm(request.POST)
#set choices filled by ajax #set choices filled by ajax
form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()] form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()]
form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=request.POST['country'])] form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=request.POST['country'])]
formset_statistic = StatisticFormSet(request.POST)
if form.is_valid():
form.save(getattr(conference, 'id')) if form.is_valid() and formset_statistic.is_valid():
conference = form.save(getattr(conference, 'id'))
#delete old halls
Statistic.objects.filter(conference=getattr(conference, 'id')).delete()
for item in formset_statistic.forms:
#saves new statistic if its valid and not empty
if item.is_valid() and item.has_changed():
statistic = item.save(commit=False)
statistic.conference = conference
statistic.save()
return HttpResponseRedirect('/admin/conference/all/') return HttpResponseRedirect('/admin/conference/all/')
else: else:
#initial StatisticFormSet
StatisticFormSet = modelformset_factory(Statistic, form=StatisticForm, exclude=('conference',))
#fill form with data from database #fill form with data from database
data = {'web_page':conference.web_page, 'foundation_year': conference.foundation_year, data = {'web_page':conference.web_page, 'foundation_year': conference.foundation_year,
'data_begin':conference.data_begin, 'data_end':conference.data_end, 'currency':conference.currency, 'data_begin':conference.data_begin, 'data_end':conference.data_end, 'currency':conference.currency,
'tax':conference.tax, 'min_price':conference.min_price, 'max_price':conference.max_price, 'tax':conference.tax, 'min_price':conference.min_price, 'max_price':conference.max_price,
'link':conference.link, 'conference_id':conference.id} 'link':conference.link, 'conference_id':conference.id, 'expohit': conference.expohit,
'discount': conference.discount,'canceled': conference.canceled, 'moved': conference.moved,
'visitors': conference.visitors, 'members': conference.members,
'quality_label': [item for item, bool in conference.quality_label if bool==True]}
if conference.country: if conference.country:
data['country'] = conference.country.id data['country'] = conference.country.id
@ -157,7 +184,7 @@ def conference_change(request, url):
data['main_title_%s' % code] = obj.main_title data['main_title_%s' % code] = obj.main_title
data['time_%s' % code] = obj.time data['time_%s' % code] = obj.time
data['main_themes_%s' % code] = obj.main_themes data['main_themes_%s' % code] = obj.main_themes
data['discount_%s' % code] = obj.discount data['discount_description_%s' % code] = obj.discount_description
data['title_%s' % code] = obj.title data['title_%s' % code] = obj.title
data['keywords_%s' % code] = obj.keywords data['keywords_%s' % code] = obj.keywords
data['descriptions_%s' % code] = obj.descriptions data['descriptions_%s' % code] = obj.descriptions
@ -166,6 +193,10 @@ def conference_change(request, url):
#set choices filled by ajax #set choices filled by ajax
form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=data['country'])] form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=data['country'])]
form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.filter(theme__in=data['theme'])] form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.filter(theme__in=data['theme'])]
#get existing statistic
statistic = Statistic.objects.filter(conference=getattr(conference, 'id'))
#fill HallFormSet
formset_statistic = StatisticFormSet(queryset=statistic)
args = {} args = {}
args.update(csrf(request)) args.update(csrf(request))
@ -173,11 +204,10 @@ def conference_change(request, url):
args['form'] = form args['form'] = form
args['languages'] = settings.LANGUAGES args['languages'] = settings.LANGUAGES
args['file_form'] = file_form args['file_form'] = file_form
args['formset_statistic'] = formset_statistic
#get list of files which connected with specific model object #get list of files which connected with specific model object
args['files'] = FileModel.objects.filter(content_type=ContentType.objects.get_for_model(conference), object_id=getattr(conference, 'id')) args['files'] = FileModel.objects.filter(content_type=ContentType.objects.get_for_model(conference), object_id=getattr(conference, 'id'))
args['obj_id'] = getattr(conference, 'id') args['obj_id'] = getattr(conference, 'id')
return render_to_response('conference_add.html', args) return render_to_response('conference_add.html', args)

@ -3,8 +3,9 @@ from django import forms
from django.conf import settings from django.conf import settings
from ckeditor.widgets import CKEditorWidget from ckeditor.widgets import CKEditorWidget
from django.forms.util import ErrorList from django.forms.util import ErrorList
from django.core.validators import validate_email, URLValidator
#models #models
from models import Conference, TimeTable, CURRENCY from models import Conference, TimeTable, CURRENCY, Statistic
from country.models import Country from country.models import Country
from city.models import City from city.models import City
from theme.models import Theme from theme.models import Theme
@ -45,11 +46,20 @@ class ConferenceCreateForm(forms.Form):
web_page = forms.CharField(label='Веб страница', required=False) web_page = forms.CharField(label='Веб страница', required=False)
link = forms.CharField(label='Линк на регистрацию', required=False) link = forms.CharField(label='Линк на регистрацию', required=False)
foundation_year = forms.CharField(label='Год основания', required=False) foundation_year = forms.CharField(label='Год основания', required=False)
members = forms.CharField(label='Посетители', required=False)
visitors = forms.CharField(label='Участники', required=False)
discount = forms.CharField(label='Cкидка(%)', required=False)
# #
currency = forms.ChoiceField(label='Валюта', choices=currencies, required=False) currency = forms.ChoiceField(label='Валюта', choices=currencies, required=False)
tax = forms.BooleanField(label='Налог включен', initial=True, required=False) tax = forms.BooleanField(label='Налог включен', initial=True, required=False)
min_price = forms.CharField(label='Минимальная цена', required=False) min_price = forms.CharField(label='Минимальная цена', required=False)
max_price = forms.CharField(label='Максимальная цена', required=False) max_price = forms.CharField(label='Максимальная цена', required=False)
expohit = forms.BooleanField(label='Expohit', required=False)
canceled = forms.BooleanField(label='Отменена', required=False)
moved = forms.BooleanField(label='Перенесена', required=False)
quality_label = forms.MultipleChoiceField(label='Тип', required=False,
choices=[('ufi', 'UFI'), ('rsva', 'РСВЯ'), ('exporating', 'ExpoRating')],
widget=forms.CheckboxSelectMultiple())
#field for comparing tmp files #field for comparing tmp files
key = forms.CharField(required=False, widget=forms.HiddenInput()) key = forms.CharField(required=False, widget=forms.HiddenInput())
# #
@ -77,14 +87,14 @@ class ConferenceCreateForm(forms.Form):
required=False, widget=CKEditorWidget) required=False, widget=CKEditorWidget)
self.fields['main_themes_%s' % code] = forms.CharField(label='Основные темы', self.fields['main_themes_%s' % code] = forms.CharField(label='Основные темы',
required=False, widget=CKEditorWidget) required=False, widget=CKEditorWidget)
self.fields['discount_%s' % code] = forms.CharField(label='Условия и скидки', self.fields['discount_description_%s' % code] = forms.CharField(label='Описание скидки',
required=False, widget=CKEditorWidget) required=False, widget=CKEditorWidget)
#meta data #meta data
self.fields['title_%s' % code] = forms.CharField(label='Тайтл', required=required, max_length=255, self.fields['title_%s' % code] = forms.CharField(label='Тайтл', required=False, max_length=255,
widget=forms.TextInput(attrs={'style':'width: 550px'})) widget=forms.TextInput(attrs={'style':'width: 550px'}))
self.fields['keywords_%s' % code] = forms.CharField(label='Дескрипшен', required=required, max_length=255, self.fields['keywords_%s' % code] = forms.CharField(label='Дескрипшен', required=False, max_length=255,
widget=forms.TextInput(attrs={'style':'width: 550px'})) widget=forms.TextInput(attrs={'style':'width: 550px'}))
self.fields['descriptions_%s' % code] = forms.CharField(label='Кейвордс', required=required, max_length=255, self.fields['descriptions_%s' % code] = forms.CharField(label='Кейвордс', required=False, max_length=255,
widget=forms.TextInput(attrs={'style':'width: 550px'})) widget=forms.TextInput(attrs={'style':'width: 550px'}))
@ -118,12 +128,26 @@ class ConferenceCreateForm(forms.Form):
conference.link = data['link'] conference.link = data['link']
conference.web_page= data['web_page'] conference.web_page= data['web_page']
conference.foundation_year = data['foundation_year'] conference.foundation_year = data['foundation_year']
conference.members = data['members']
conference.visitors = data['visitors']
# #
conference.currency = data['currency'] conference.currency = data['currency']
conference.tax = data['tax'] conference.tax = data['tax']
conference.min_price = data['min_price'] conference.min_price = data['min_price']
conference.max_price = data['max_price'] conference.max_price = data['max_price']
conference.discount = data['discount']
conference.expohit = data['expohit']
conference.canceled = data['canceled']
conference.moved = data['moved']
# generates bitfield
flag = 0
if data['quality_label']:
flag = reduce(lambda x,y: x|y, (getattr(Conference.quality_label, item) for item in data['quality_label']))
conference.quality_label = flag
if data.get('country'): if data.get('country'):
conference.country = Country.objects.get(id=data['country'].id)#.id cause select uses queryset conference.country = Country.objects.get(id=data['country'].id)#.id cause select uses queryset
@ -147,6 +171,7 @@ class ConferenceCreateForm(forms.Form):
#save files #save files
check_tmp_files(conference, data['key']) check_tmp_files(conference, data['key'])
return conference
def clean(self): def clean(self):
id = self.cleaned_data.get('conference_id') id = self.cleaned_data.get('conference_id')
@ -167,30 +192,31 @@ class ConferenceCreateForm(forms.Form):
cleaned_data = super(ConferenceCreateForm, self).clean() cleaned_data = super(ConferenceCreateForm, self).clean()
web_page = cleaned_data.get('web_page') web_page = cleaned_data.get('web_page')
if not web_page: if not web_page:
return web_page return ''
import socket validate = URLValidator()
try: try:
socket.getaddrinfo(web_page, 80) validate(web_page)
return web_page except(forms.ValidationError),e:
except: raise forms.ValidationError(e.messages[0])
raise forms.ValidationError('Введите правильный адрес страници') return web_page
def clean_link(self): def clean_link(self):
""" """
checking link checking link
""" """
cleaned_data = super(ConferenceCreateForm, self).clean() cleaned_data = super(ConferenceCreateForm, self).clean()
link = cleaned_data.get('link') link = cleaned_data.get('link')
if not link: if not link:
return link return ''
import socket validate = URLValidator()
try: try:
socket.getaddrinfo(link, 80) validate(link)
return link except(forms.ValidationError),e:
except: raise forms.ValidationError(e.messages[0])
raise forms.ValidationError('Введите правильный адрес страници') return link
def clean_foundation_year(self): def clean_foundation_year(self):
@ -201,6 +227,22 @@ class ConferenceCreateForm(forms.Form):
foundation_year = cleaned_data.get('foundation_year').strip() foundation_year = cleaned_data.get('foundation_year').strip()
return is_positive_integer(foundation_year) return is_positive_integer(foundation_year)
def clean_visitors(self):
"""
checking visitors
"""
cleaned_data = super(ConferenceCreateForm, self).clean()
visitors = cleaned_data.get('visitors').strip()
return is_positive_integer(visitors)
def clean_members(self):
"""
checking members
"""
cleaned_data = super(ConferenceCreateForm, self).clean()
members = cleaned_data.get('members').strip()
return is_positive_integer(members)
def clean_min_price(self): def clean_min_price(self):
""" """
checking min_price checking min_price
@ -217,6 +259,14 @@ class ConferenceCreateForm(forms.Form):
max_price = cleaned_data.get('max_price').strip() max_price = cleaned_data.get('max_price').strip()
return is_positive_integer(max_price) return is_positive_integer(max_price)
def clean_discount(self):
"""
checking discount
"""
cleaned_data = super(ConferenceCreateForm, self).clean()
discount = cleaned_data.get('discount').strip()
return is_positive_integer(discount)
class ConferenceChangeForm(ConferenceCreateForm): class ConferenceChangeForm(ConferenceCreateForm):
""" """
@ -236,6 +286,30 @@ class ConferenceDeleteForm(forms.ModelForm):
model = Conference model = Conference
fields = ('url',) fields = ('url',)
class StatisticForm(forms.ModelForm):
year = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}))
visitors = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False)
members = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False)
class Meta:
model = Statistic
exclude = ('conference')
def clean_year(self):
cleaned_data = super(StatisticForm, self).clean()
year = cleaned_data.get('year').strip()
return is_positive_integer(year)
def clean_members(self):
cleaned_data = super(StatisticForm, self).clean()
members = cleaned_data.get('members').strip()
return is_positive_integer(members)
def clean_visitors(self):
cleaned_data = super(StatisticForm, self).clean()
visitors = cleaned_data.get('visitors').strip()
return is_positive_integer(visitors)
class TimeTableForm(forms.Form): class TimeTableForm(forms.Form):
""" """

@ -1,32 +1,31 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
from django.db.models.signals import post_save, pre_save
from django.contrib.contenttypes import generic
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from functions.signal_handlers import post_save_handler, pre_save_handler
import copy import copy
from bitfield import BitField
from service.models import Service
from functions.db import db_table_exists
#custom functions #custom functions
from functions.custom_fields import EnumField from functions.custom_fields import EnumField
from functions.models_methods import ExpoManager
from functions.model_mixin import EventMixin
# check if table exist and create flags if true
flags = [str(item.id) for item in Service.objects.all()] if db_table_exists('service_service') else []
class ConferenceManager(TranslationManager):
def safe_get(self, **kwargs):
model = self.model
try:
return model.objects.get(**kwargs)
except:
return None
CURRENCY = ('RUB', 'USD', 'EUR') CURRENCY = ('RUB', 'USD', 'EUR')
class Conference(TranslatableModel): class Conference(TranslatableModel, EventMixin):
""" """
Create Conference model Create Conference model
Uses hvad.TranslatableModel which is child of django.db.models class Uses hvad.TranslatableModel which is child of django.db.models class
""" """
#set manager of this model #set manager of this model
objects = ConferenceManager() objects = ExpoManager()
url = models.SlugField(unique=True) url = models.SlugField(unique=True)
data_begin = models.DateField(verbose_name='Дата начала') data_begin = models.DateField(verbose_name='Дата начала')
@ -43,23 +42,34 @@ class Conference(TranslatableModel):
organiser = models.ManyToManyField('organiser.Organiser', verbose_name='Организатор', organiser = models.ManyToManyField('organiser.Organiser', verbose_name='Организатор',
blank=True, null=True, related_name='conference_organisers') blank=True, null=True, related_name='conference_organisers')
company = models.ManyToManyField('company.Company', verbose_name='Компании', company = models.ManyToManyField('company.Company', verbose_name='Компании',
blank=True, null=True, related_name='conference_compamies') blank=True, null=True, related_name='conference_companies')
users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки', users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки',
blank=True, null=True, related_name='conference_users') blank=True, null=True, related_name='conference_users')
#!service has bitfield uncomment when country data will be filled #!service has bitfield uncomment when country data will be filled
services = BitField(flags=flags)
#service = models.ManyToManyField('service.Service', verbose_name='Услуги', blank=True, null=True) #service = models.ManyToManyField('service.Service', verbose_name='Услуги', blank=True, null=True)
web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True) web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True)
link = models.CharField(verbose_name='Линк на регистрацию', max_length=255, blank=True) link = models.CharField(verbose_name='Линк на регистрацию', max_length=255, blank=True)
foundation_year = models.PositiveIntegerField(verbose_name='Год основания', blank=True, null=True) quality_label = BitField(flags=['ufi', 'rsva', 'exporating'])
discount = models.PositiveIntegerField(verbose_name='Скидка', blank=True, null=True)
# #
currency = EnumField(values=CURRENCY, default='RUB') currency = EnumField(values=CURRENCY, default='RUB')
tax = models.BooleanField(verbose_name='Налог', default=1) tax = models.BooleanField(verbose_name='Налог', default=1)
min_price = models.PositiveIntegerField(verbose_name='Минимальная цена', blank=True, null=True) min_price = models.PositiveIntegerField(verbose_name='Минимальная цена', blank=True, null=True)
max_price = models.PositiveIntegerField(verbose_name='Максимальная цена', blank=True, null=True) max_price = models.PositiveIntegerField(verbose_name='Максимальная цена', blank=True, null=True)
#administrator can cancel conference #administrator can cancel conference
expohit = models.BooleanField(verbose_name='Expohit', default=0)
canceled_by_administrator = models.BooleanField(default=0) canceled_by_administrator = models.BooleanField(default=0)
canceled = models.BooleanField(default=0)
moved = models.BooleanField(default=0)
#can publish not immediately #can publish not immediately
is_published = models.BooleanField(default=0) is_published = models.BooleanField(default=0)
files = generic.GenericRelation('file.FileModel', content_type_field='content_type', object_id_field='object_id')
# statistic
foundation_year = models.PositiveIntegerField(verbose_name='Год основания', blank=True, null=True)
visitors = models.PositiveIntegerField(verbose_name='Посетитеил', blank=True, null=True)
members = models.PositiveIntegerField(verbose_name='Участники', blank=True, null=True)
#translated fields #translated fields
translations = TranslatedFields( translations = TranslatedFields(
name = models.CharField(verbose_name='Название', max_length=255), name = models.CharField(verbose_name='Название', max_length=255),
@ -67,7 +77,7 @@ class Conference(TranslatableModel):
description=models.TextField(verbose_name='Описание', blank=True), description=models.TextField(verbose_name='Описание', blank=True),
main_themes=models.TextField(verbose_name='Основные темы', blank=True), main_themes=models.TextField(verbose_name='Основные темы', blank=True),
time=models.TextField(verbose_name='Время работы', blank=True), time=models.TextField(verbose_name='Время работы', blank=True),
discount=models.TextField(verbose_name='Условия и Скидки', blank=True), discount_description=models.TextField(verbose_name='Описание скидки', blank=True),
#-----meta data #-----meta data
title=models.CharField(max_length=250), title=models.CharField(max_length=250),
descriptions=models.CharField(max_length=250), descriptions=models.CharField(max_length=250),
@ -78,25 +88,17 @@ class Conference(TranslatableModel):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
#audience = EnumField(values=AUDIENCE) views = models.PositiveIntegerField(null=True)
#mark
def __unicode__(self): def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk)) return self.lazy_translation_getter('name', unicode(self.pk))
def on(self): def get_nearest_events(self):
self.is_published = True conferences = Conference.objects.all()[:5]
self.canceled_by_administrator = False return conferences
self.save()
def off(self): def get_catalog_url(self):
self.is_published = False return '/conferences/'
self.canceled_by_administrator = True
self.save()
def cancel(self):
self.canceled_by_administrator = True
def clone(self): def clone(self):
""" """
@ -118,6 +120,16 @@ class Conference(TranslatableModel):
duplicate.is_published = False duplicate.is_published = False
duplicate.cancel_by_administrator = False duplicate.cancel_by_administrator = False
ignore_fields = ['id', 'master', 'language_code']
duplicate.translate('ru')
tr = self._meta.translations_model.objects.get(language_code = 'ru',master__id=self.pk)
for field in duplicate._translated_field_names:
if field in ignore_fields:
continue
setattr(duplicate, field, getattr(tr, field))
duplicate.save() duplicate.save()
# but lost all ManyToMany relations and Translations. # but lost all ManyToMany relations and Translations.
@ -128,23 +140,20 @@ class Conference(TranslatableModel):
for item in source.all(): for item in source.all():
destination.add(item) destination.add(item)
# copy translations return duplicate
languages = self.get_available_languages()
ignore_fields = ['id', 'master', 'language_code']
for code in languages:
duplicate.translate(code)
tr = self._meta.translations_model.objects.get(language_code = code,master__id=self.pk)
for field in duplicate._translated_field_names:
if field in ignore_fields: def get_calendar_url(self):
continue return '/conference-add-calendar/%s/'%self.id
setattr(duplicate, field, getattr(tr, field)) def get_visit_url(self):
return '/conference-visit/%s/'%self.id
duplicate.save()
return duplicate class Statistic(models.Model):
conference = models.ForeignKey(Conference, related_name='statistic')
year = models.PositiveIntegerField(verbose_name='Год')
members = models.PositiveIntegerField(verbose_name='Посетители')
visitors = models.PositiveIntegerField(verbose_name='Участники')
class TimeTable(TranslatableModel): class TimeTable(TranslatableModel):
@ -158,4 +167,7 @@ class TimeTable(TranslatableModel):
#translated fields #translated fields
translations = TranslatedFields( translations = TranslatedFields(
name = models.CharField(verbose_name='Название', max_length=255) name = models.CharField(verbose_name='Название', max_length=255)
) )
pre_save.connect(pre_save_handler, sender=Conference)
post_save.connect(post_save_handler, sender=Conference)

@ -3,4 +3,4 @@ from django.db.models.signals import post_save
from models import Conference from models import Conference
from functions.signal_handlers import post_save_handler from functions.signal_handlers import post_save_handler
post_save.connect(post_save_handler, sender=Conference) #post_save.connect(post_save_handler, sender=Conference)

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from views import ConferenceView
urlpatterns = patterns('',
url(r'conferences/(?P<params>.*)/(?P<page>\d+)/$', ConferenceView.as_view()),
url(r'conferences/(?P<page>\d+)/$', ConferenceView.as_view()),
url(r'conferences/(?P<params>.*)/$', ConferenceView.as_view()),
url(r'conferences/$', ConferenceView.as_view()),
#
url(r'conference-add-calendar/(?P<id>\d+)/$', 'conference.views.conference_add_calendar'),
url(r'conference-remove-calendar/(?P<id>\d+)/$', 'conference.views.conference_remove_calendar'),
url(r'conference-visit/(?P<id>\d+)/$', 'conference.views.conference_visit'),
url(r'conference-unvisit/(?P<id>\d+)/$', 'conference.views.conference_unvisit'),
)

@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from models import Conference
from functions.custom_views import ExpoListView
import json
class ConferenceView(ExpoListView):
model = Conference
template_name = 'event_catalog.html'
def conference_add_calendar(request, id):
args = {'success': False}
user = request.user
if user.is_authenticated():
conf = Conference.objects.safe_get(id=id)
if conf:
user.calendar.conferences.add(conf)
args['success'] = True
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')
def conference_remove_calendar(request, id):
args = {'success': False}
if request.user:
user = request.user
conf = Conference.objects.safe_get(id=id)
if conf:
user.calendar.conferences.remove(conf)
args['success'] = True
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')
def conference_visit(request, id):
args = {'success': False}
user = request.user
if user.is_authenticated():
conf = Conference.objects.safe_get(id=id)
if conf:
conf.users.add(user)
args['success'] = True
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')
def conference_unvisit(request, id):
args = {'success': False}
user = request.user
if user.is_authenticated():
conf = Conference.objects.safe_get(id=id)
if conf:
conf.users.remove(user)
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

@ -0,0 +1,16 @@
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)

@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
from country.models import Country
from city.models import City
from place_exposition.models import PlaceExposition
from place_conference.models import PlaceConference
from django.views.generic import ListView
from functions.views_help import split_params
from django.utils.translation import ugettext as _
class PlaceListView(ListView):
paginate_by = 2
params = None
single_page = False
template_name = 'place_catalog_test.html'
model = 'places'
def get_params(self):
model_names = {'places': _(u'Места')}
model_alternative_name = {'places': 'place'}
params = [{'type':'model', 'url':self.model, 'name': model_names.get(self.model),
'alternative_name': model_alternative_name.get(self.model)}]
st = self.kwargs.get('params')
if st:
params = params + split_params(st)
return params
def get_queryset(self):
pl_ex = PlaceExposition.objects.all()
pl_conf = PlaceConference.objects.all()
params = self.get_params()
for param in params:
if param.get('type') == 'country':
country = Country.objects.safe_get(url=param.get('url'))
if country:
param['name'] = country.name
pl_ex = pl_ex.filter(country=country)
pl_conf = pl_conf.filter(country=country)
if param.get('type') == 'city':
city = City.objects.safe_get(url=param.get('url'))
if city:
param['name'] = city.name
pl_ex = pl_ex.filter(city=city)
pl_conf = pl_conf.filter(city=city)
if param.get('type') == 'place':
pl_ex = pl_ex.filter(url=param.get('url'))
if pl_ex:
query = pl_ex
else:
query = pl_conf.filter(url=param.get('url'))
self.single_page = True
if query:
param['name'] = query[0].name
#if self.request:
# views = query[0].views
# query.update(views=views+1)
self.params = params
return query
self.params = params
return list(pl_ex) + list(pl_conf)
def get_context_data(self, **kwargs):
context = super(PlaceListView, self).get_context_data(**kwargs)
context['filter'] = self.params
context['single_page'] = self.single_page
return context

@ -13,12 +13,26 @@ from forms import CountryForm, CountryDeleteForm
from file.models import FileModel, TmpFile from file.models import FileModel, TmpFile
from file.forms import FileModelForm from file.forms import FileModelForm
#custom views #custom views
from functions.custom_views import objects_list, add_object_with_file, delete_object from functions.custom_views import objects_list, add_object_with_file, delete_object, filtered_list
from functions.forms import AdminSearchForm
from hvad.utils import get_translation_aware_manager
def country_all(request): def country_all(request):
""" """
Return list of all countries with pagination Return list of all countries with pagination
""" """
if request.GET:
form = AdminSearchForm(request.POST)
if form.is_valid():
s_name = request.GET.get('search_name')
query = get_translation_aware_manager(Country)
objects = query.filter(name__contains=s_name).distinct()
#return HttpResponse(objects)
#objects = Country.objects.all()
return filtered_list(request, objects, 'country_all.html', 1000)
return objects_list(request, Country, 'country_all.html') return objects_list(request, Country, 'country_all.html')
def country_add(request): def country_add(request):

@ -2,10 +2,11 @@
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from ckeditor.widgets import CKEditorWidget from ckeditor.widgets import CKEditorWidget
from tinymce.widgets import TinyMCE
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms.util import ErrorList from django.forms.util import ErrorList
#models #models
from models import Country, City from models import Country, City, REGIONS
from directories.models import Language, Currency, Iata from directories.models import Language, Currency, Iata
#functions #functions
from functions.translate import fill_with_signal from functions.translate import fill_with_signal
@ -45,14 +46,14 @@ class CountryForm(forms.Form):
# #
population = forms.CharField(label='Население(млн)', required=False, population = forms.CharField(label='Население(млн)', required=False,
widget=forms.TextInput(attrs={'placeholder':'Население(млн)'})) widget=forms.TextInput(attrs={'placeholder':'Население(млн)'}))
teritory = forms.CharField(label='Територия(км2)', required=False, teritory = forms.CharField(label='Территория(км2)', required=False,
widget=forms.TextInput(attrs={'placeholder':'Територия(км2)'}))# km2 widget=forms.TextInput(attrs={'placeholder':'Територия(км2)'}))# km2
timezone = forms.ChoiceField(label='Часовые пояса', required=False, choices=tz, initial=99) timezone = forms.ChoiceField(label='Часовые пояса', required=False, choices=tz, initial=99)
phone_code = forms.CharField(label='Код страны', required=False, phone_code = forms.CharField(label='Код страны', required=False,
widget=forms.TextInput(attrs={'placeholder':'Код страны'})) widget=forms.TextInput(attrs={'placeholder':'Код страны'}))
time_delivery = forms.CharField(label='Срок выдачи', required=False, time_delivery = forms.CharField(label='Срок выдачи', required=False,
widget=forms.TextInput(attrs={'placeholder':'Срок выдачи'})) widget=forms.TextInput(attrs={'placeholder':'Срок выдачи'}))
region = forms.ChoiceField(label='Регион', choices=((item, item) for item in Country.REGIONS)) region = forms.ChoiceField(label='Регион', choices=((item, item) for item in REGIONS))
#services = forms.MultipleChoiceField(label='Сервисы', required=False, choices=); #services = forms.MultipleChoiceField(label='Сервисы', required=False, choices=);
#field for comparing tmp files #field for comparing tmp files
@ -61,7 +62,7 @@ class CountryForm(forms.Form):
country_id = forms.CharField(required=False, widget=forms.HiddenInput) country_id = forms.CharField(required=False, widget=forms.HiddenInput)
def __init__(self, *args, **kwargs ): def __init__(self, *args, **kwargs):
""" """
creates dynamical translated fields and fills select fields creates dynamical translated fields and fills select fields
@ -95,17 +96,17 @@ class CountryForm(forms.Form):
widget=forms.TextInput(attrs={'style':'width: 550px'})) widget=forms.TextInput(attrs={'style':'width: 550px'}))
# check if exists cities connected with country # check if exists cities connected with country
countries = City.objects.filter(country = country_id) countries = City.objects.language().filter(country = country_id).order_by('name')
countries_list = [(item.id, item.name) for item in countries] countries_list = [(item.id, item.name) for item in countries]
if country_id == None or len(countries)==0: if country_id == None or len(countries)==0:
self.fields['capital'] = forms.ChoiceField(label='Столица',choices=((None,'Нет городов в стране'),), required=False, self.fields['capital'] = forms.ChoiceField(label='Столица',choices=((None,'Нет городов в стране'),), required=False,
widget=forms.Select(attrs={'disabled' : True})) widget=forms.Select(attrs={'disabled' : True}))
self.fields['big_cities'] = forms.MultipleChoiceField(label='Большые города',choices=((None,'Нет городов в стране'),), required=False, self.fields['big_cities'] = forms.MultipleChoiceField(label='Большие города',choices=((None,'Нет городов в стране'),), required=False,
widget=forms.Select(attrs={'disabled' : True})) widget=forms.Select(attrs={'disabled' : True}))
else: else:
self.fields['capital'] = forms.ChoiceField(label='Столица', choices=countries_list, self.fields['capital'] = forms.ChoiceField(label='Столица', choices=countries_list,
required=False) required=False)
self.fields['big_cities'] = forms.MultipleChoiceField(label='Большые города', choices=countries_list, self.fields['big_cities'] = forms.MultipleChoiceField(label='Большие города', choices=countries_list,
required=False) required=False)
def save(self, id=None): def save(self, id=None):
@ -126,8 +127,11 @@ class CountryForm(forms.Form):
country.language.clear() country.language.clear()
country.currency.clear() country.currency.clear()
if data.get("name_en"):
country.url = translit_with_separator(data['name_en'].strip()).lower()
else:
country.url = translit_with_separator(data['name_ru'].strip()).lower()
country.url = translit_with_separator(data['name_ru'].strip()).lower()
country.population = data['population'] country.population = data['population']
country.teritory = data['teritory'] country.teritory = data['teritory']
country.timezone = data['timezone'] country.timezone = data['timezone']

@ -1,19 +1,37 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
from hvad.models import TranslatableModel, TranslatedFields from django.utils.translation import ugettext as _
from django.contrib.contenttypes import generic from django.contrib.contenttypes import generic
from django.db.models.signals import post_save, pre_save
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from bitfield import BitField
# models # models
from directories.models import Language, Currency from directories.models import Language, Currency
from city.models import City from city.models import City
from service.models import Service from service.models import Service
# func # func
from functions.custom_fields import EnumField from functions.custom_fields import EnumField
from bitfield import BitField
from functions.db import db_table_exists from functions.db import db_table_exists
from functions.signal_handlers import post_save_handler, pre_save_handler
from django.utils.translation import get_language as lang
# check if table exist and create flags if true # check if table exist and create flags if true
flags = [str(item.id) for item in Service.objects.all()] if db_table_exists('service_service') else [] flags = [str(item.id) for item in Service.objects.all()] if db_table_exists('service_service') else []
REGIONS =('europa', 'asia', 'america', 'africa')
class CountryManager(TranslationManager):
def all(self):
"""
hack
"""
return super(TranslationManager, self).all().filter(translations__language_code=lang()).order_by('translations__name')
def safe_get(self, **kwargs):
model = self.model
try:
return model.objects.get(**kwargs)
except:
return None
class Country(TranslatableModel): class Country(TranslatableModel):
""" """
@ -23,11 +41,8 @@ class Country(TranslatableModel):
""" """
objects = CountryManager()
services = BitField(flags=flags) services = BitField(flags=flags)
REGIONS =('europa', 'asia', 'america', 'africa')
url = models.SlugField(unique=True) url = models.SlugField(unique=True)
# relations # relations
big_cities = models.ManyToManyField(City, blank=True, null=True, related_name='cities') big_cities = models.ManyToManyField(City, blank=True, null=True, related_name='cities')
@ -50,7 +65,7 @@ class Country(TranslatableModel):
files = generic.GenericRelation('file.FileModel',content_type_field='content_type', object_id_field='object_id') files = generic.GenericRelation('file.FileModel',content_type_field='content_type', object_id_field='object_id')
#translated fields #translated fields
translations = TranslatedFields( translations = TranslatedFields(
name = models.CharField(max_length=30), name = models.CharField(max_length=255),
description = models.TextField(blank=True), description = models.TextField(blank=True),
transport = models.TextField(blank=True), transport = models.TextField(blank=True),
#------visa inf #------visa inf
@ -64,5 +79,10 @@ class Country(TranslatableModel):
) )
# class Meta:
# ordering = ['translations__name']
def __unicode__(self): def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk)) return self.lazy_translation_getter('name', unicode(self.pk))
post_save.connect(post_save_handler, sender=Country)

@ -1,9 +1 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db.models.signals import post_save
from functions.signal_handlers import post_save_handler
from models import Country
post_save.connect(post_save_handler, sender=Country)

@ -7,16 +7,16 @@ from django.forms.formsets import BaseFormSet, formset_factory
from django.forms.models import modelformset_factory from django.forms.models import modelformset_factory
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
#models and forms # models and forms
from models import Exposition, TimeTable from models import Exposition, TimeTable, Statistic, TmpTimeTable
from forms import ExpositionChangeForm, ExpositionCreateForm, ExpositionDeleteForm, TimeTableForm from forms import ExpositionCreateForm, ExpositionDeleteForm, TimeTableForm, StatisticForm
from theme.models import Tag from theme.models import Tag
from city.models import City from city.models import City
from file.models import FileModel, TmpFile from file.models import FileModel, TmpFile
from file.forms import FileModelForm from file.forms import FileModelForm
#python # python
import random import random
#custom views # custom views
from functions.custom_views import objects_list, delete_object from functions.custom_views import objects_list, delete_object
from functions.views_help import get_referer from functions.views_help import get_referer
@ -52,7 +52,6 @@ def exposition_switch(request, url, action):
return HttpResponse('error') return HttpResponse('error')
@login_required @login_required
def exposition_copy(request, url): def exposition_copy(request, url):
@ -63,6 +62,7 @@ def exposition_copy(request, url):
exposition.clone() exposition.clone()
return HttpResponseRedirect(get_referer(request)) return HttpResponseRedirect(get_referer(request))
@login_required @login_required
def exposition_add(request): def exposition_add(request):
""" """
@ -70,25 +70,37 @@ def exposition_add(request):
If form is posted redirect on the page of all expositions. If form is posted redirect on the page of all expositions.
""" """
#if form would be not valid key must be same # formset of StatisticForm
StatisticFormSet = formset_factory(StatisticForm)
# if form would be not valid key must be same
if request.POST.get('key'): if request.POST.get('key'):
key = request.POST['key'] key = request.POST['key']
else: else:
key = random.getrandbits(128) key = random.getrandbits(128)
file_form = FileModelForm(initial={'key': key}) file_form = FileModelForm(initial={'key': key})
timetable_form = TimeTableForm(initial={'key': key})
if request.POST: if request.POST:
form = ExpositionCreateForm(request.POST) form = ExpositionCreateForm(request.POST)
#set choices filled by ajax # set choices filled by ajax
form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()] form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()]
form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=request.POST['country'])] form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=request.POST['country'])]
if form.is_valid(): formset_statistic = StatisticFormSet(request.POST)
form.save()
if form.is_valid() and formset_statistic.is_valid():
exposition = form.save()
for item in formset_statistic.forms:
# saves forms if its valid and not empty
if item.is_valid() and item.has_changed():
statistic = item.save(commit=False)
statistic.exposition = exposition
statistic.save()
return HttpResponseRedirect('/admin/exposition/all/') return HttpResponseRedirect('/admin/exposition/all/')
else: else:
form = ExpositionCreateForm(initial={'key': key}) form = ExpositionCreateForm(initial={'key': key})
formset_statistic = StatisticFormSet()
args = {} args = {}
args.update(csrf(request)) args.update(csrf(request))
@ -96,7 +108,12 @@ def exposition_add(request):
args['form'] = form args['form'] = form
args['file_form'] = file_form args['file_form'] = file_form
args['files'] = TmpFile.objects.filter(key=key) args['files'] = TmpFile.objects.filter(key=key)
args['timetables'] = TmpTimeTable.objects.filter(key=key)
args['languages'] = settings.LANGUAGES args['languages'] = settings.LANGUAGES
args['formset_statistic'] = formset_statistic
args['timetable_form'] = timetable_form
return render_to_response('exposition_add.html', args) return render_to_response('exposition_add.html', args)
@ -113,31 +130,51 @@ def exposition_change(request, url):
""" """
try: try:
#check if exposition_id exists else redirect to the list of expositions # check if exposition_id exists else redirect to the list of expositions
exposition = Exposition.objects.get(url=url) exposition = Exposition.objects.get(url=url)
file_form = FileModelForm(initial={'model': 'exposition.Exposition'}) file_form = FileModelForm(initial={'model': 'exposition.Exposition'})
except: except:
return HttpResponseRedirect('/admin/exposition/all/') return HttpResponseRedirect('/admin/exposition/all/')
if request.POST: if request.POST:
form = ExpositionChangeForm(request.POST) StatisticFormSet = formset_factory(StatisticForm)
#set choices filled by ajax form = ExpositionCreateForm(request.POST)
# set choices filled by ajax
form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()] form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()]
form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=request.POST['country'])] form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=request.POST['country'])]
formset_statistic = StatisticFormSet(request.POST)
if form.is_valid() and formset_statistic.is_valid():
exposition = form.save(getattr(exposition, 'id'))
# delete old halls
Statistic.objects.filter(exposition=getattr(exposition, 'id')).delete()
for item in formset_statistic.forms:
# saves new statistic if its valid and not empty
if item.is_valid() and item.has_changed():
statistic = item.save(commit=False)
statistic.exposition = exposition
statistic.save()
if form.is_valid():
form.save(getattr(exposition, 'id'))
return HttpResponseRedirect('/admin/exposition/all/') return HttpResponseRedirect('/admin/exposition/all/')
else: else:
#fill form with data from database # initial StatisticFormSet
StatisticFormSet = modelformset_factory(Statistic, form=StatisticForm, exclude=('exposition',))
# fill form with data from database
data = {'web_page':exposition.web_page, 'foundation_year': exposition.foundation_year, data = {'web_page':exposition.web_page, 'foundation_year': exposition.foundation_year,
'data_begin':exposition.data_begin, 'data_end':exposition.data_end, 'periodic':exposition.periodic, 'data_begin':exposition.data_begin, 'data_end':exposition.data_end, 'periodic':exposition.periodic,
'audience':exposition.audience, 'min_area':exposition.min_area, 'currency':exposition.currency, 'min_area':exposition.min_area, 'currency':exposition.currency, 'tax':exposition.tax,
'tax':exposition.tax, 'min_closed_area':exposition.min_closed_area, 'price_day':exposition.price_day, 'price_all':exposition.price_all, 'price_catalog':exposition.price_catalog,
'max_closed_area':exposition.max_closed_area, 'min_closed_equipped_area':exposition.min_closed_equipped_area, 'min_closed_area':exposition.min_closed_area, 'max_closed_area':exposition.max_closed_area,
'min_closed_equipped_area':exposition.min_closed_equipped_area,
'max_closed_equipped_area':exposition.max_closed_equipped_area, 'max_closed_equipped_area':exposition.max_closed_equipped_area,
'min_open_area':exposition.min_open_area, 'max_open_area':exposition.max_open_area, 'min_open_area':exposition.min_open_area, 'max_open_area':exposition.max_open_area,
'registration_payment':exposition.registration_payment, 'exposition_id':exposition.id} 'registration_payment':exposition.registration_payment, 'exposition_id':exposition.id,
'expohit': exposition.expohit, 'discount': exposition.discount,
'canceled': exposition.canceled, 'moved': exposition.moved,
'visitors': exposition.visitors, 'members': exposition.members,
'audience':[item for item, bool in exposition.audience if bool==True],
'quality_label': [item for item, bool in exposition.quality_label if bool==True]}
if exposition.country: if exposition.country:
data['country'] = exposition.country.id data['country'] = exposition.country.id
@ -150,7 +187,9 @@ def exposition_change(request, url):
data['theme'] = [item.id for item in exposition.theme.all()] data['theme'] = [item.id for item in exposition.theme.all()]
data['tag'] = [item.id for item in exposition.tag.all()] data['tag'] = [item.id for item in exposition.tag.all()]
#data from translated fields data['organiser'] = [item.id for item in exposition.organiser.all()]
data['company'] = [item.id for item in exposition.company.all()]
# data from translated fields
for code, name in settings.LANGUAGES: for code, name in settings.LANGUAGES:
obj = Exposition._meta.translations_model.objects.get(language_code = code,master__id=getattr(exposition, 'id')) #access to translated fields obj = Exposition._meta.translations_model.objects.get(language_code = code,master__id=getattr(exposition, 'id')) #access to translated fields
data['name_%s' % code] = obj.name data['name_%s' % code] = obj.name
@ -158,14 +197,19 @@ def exposition_change(request, url):
data['main_title_%s' % code] = obj.main_title data['main_title_%s' % code] = obj.main_title
data['time_%s' % code] = obj.time data['time_%s' % code] = obj.time
data['products_%s' % code] = obj.products data['products_%s' % code] = obj.products
data['discount_description_%s' % code] = obj.discount_description
data['title_%s' % code] = obj.title data['title_%s' % code] = obj.title
data['keywords_%s' % code] = obj.keywords data['keywords_%s' % code] = obj.keywords
data['descriptions_%s' % code] = obj.descriptions data['descriptions_%s' % code] = obj.descriptions
#initial form # initial form
form = ExpositionChangeForm(initial=data) form = ExpositionCreateForm(initial=data)
#set choices filled by ajax # set choices filled by ajax
form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=data['country'])] form.fields['city'].choices = [(item.id, item.name) for item in City.objects.filter(country=data['country'])]
form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.filter(theme__in=data['theme'])] form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.filter(theme__in=data['theme'])]
# get existing statistic
statistic = Statistic.objects.filter(exposition=getattr(exposition, 'id'))
# fill HallFormSet
formset_statistic = StatisticFormSet(queryset=statistic)
args = {} args = {}
args.update(csrf(request)) args.update(csrf(request))
@ -173,10 +217,13 @@ def exposition_change(request, url):
args['form'] = form args['form'] = form
args['languages'] = settings.LANGUAGES args['languages'] = settings.LANGUAGES
args['file_form'] = file_form args['file_form'] = file_form
args['formset_statistic'] = formset_statistic
args['timetable_form'] = TimeTableForm()
args['timetables'] = TimeTable.objects.filter(exposition=exposition)
#get list of files which connected with specific model object # get list of files which connected with specific model object
args['files'] = FileModel.objects.filter(content_type=ContentType.objects.get_for_model(exposition), args['files'] = FileModel.objects.filter(content_type=ContentType.objects.get_for_model(exposition),
object_id=getattr(exposition, 'id')) object_id=getattr(exposition, 'id'))
args['obj_id'] = getattr(exposition, 'id') args['obj_id'] = getattr(exposition, 'id')
return render_to_response('exposition_add.html', args) return render_to_response('exposition_add.html', args)

@ -2,10 +2,12 @@
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from ckeditor.widgets import CKEditorWidget from ckeditor.widgets import CKEditorWidget
from tinymce.widgets import TinyMCE
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms.util import ErrorList from django.forms.util import ErrorList
from django.core.validators import validate_email, URLValidator
#models #models
from models import Exposition, TimeTable, AUDIENCE1, CURRENCY from models import Exposition, TimeTable, TmpTimeTable, AUDIENCE1, CURRENCY, Statistic, BIT_AUDIENCE
from country.models import Country from country.models import Country
from theme.models import Theme from theme.models import Theme
from organiser.models import Organiser from organiser.models import Organiser
@ -19,6 +21,7 @@ from functions.translate import populate_all, fill_trans_fields_all, fill_with_s
from functions.form_check import is_positive_integer from functions.form_check import is_positive_integer
from functions.files import check_tmp_files from functions.files import check_tmp_files
from functions.form_check import translit_with_separator from functions.form_check import translit_with_separator
from settings.settings import date_formats
class ExpositionCreateForm(forms.Form): class ExpositionCreateForm(forms.Form):
@ -29,39 +32,54 @@ class ExpositionCreateForm(forms.Form):
save function saves data in Exposition object. If it doesnt exist create new object save function saves data in Exposition object. If it doesnt exist create new object
""" """
PERIODIC = ((0, 'Не выбрано'), PERIODIC = ((0, u'Не выбрано'),
(1.0, 'Ежегодно'), (2.0, '2 раза в год'), (3.0, '3 раза в год'), (1.0, u'Ежегодно'), (2.0, u'2 раза в год'), (3.0, u'3 раза в год'),
(4.0, '4 раза в год'), (5.0, '5 раз в год'), (4.0, u'4 раза в год'), (5.0, u'5 раз в год'),
(0.5, 'Раз в 2 года'),(0.33, 'Раз в 3 года'),(0.25, 'Раз в 4 года')) (0.5, u'Раз в 2 года'),(0.33, u'Раз в 3 года'),(0.25, u'Раз в 4 года'))
public = [(item1, item2) for item1, item2 in AUDIENCE1] public = [(item1, item2) for item1, item2 in BIT_AUDIENCE]
currencies = [(item, item) for item in CURRENCY] currencies = [(item, item) for item in CURRENCY]
data_begin = forms.DateField(label='Дата начала') data_begin = forms.DateField(label=u'Дата начала')
data_end = forms.DateField(label='Дата окночания') data_end = forms.DateField(label=u'Дата окночания')
country = forms.ModelChoiceField(label='Страна', queryset=Country.objects.all(), empty_label=None) organiser = forms.ModelMultipleChoiceField(label=u'Организаторы', queryset=Organiser.objects.all(), required=False)
theme = forms.ModelMultipleChoiceField(label='Тематики', queryset=Theme.objects.all()) company = forms.ModelMultipleChoiceField(label=u'Компании', queryset=Company.objects.all(), required=False)
place = forms.ModelChoiceField(label='Место проведения', queryset=PlaceExposition.objects.all(), country = forms.ModelChoiceField(label=u'Страна', queryset=Country.objects.all(), empty_label=None)
theme = forms.ModelMultipleChoiceField(label=u'Тематики', queryset=Theme.objects.all())
place = forms.ModelChoiceField(label=u'Место проведения', queryset=PlaceExposition.objects.all(),
empty_label='', required=False) empty_label='', required=False)
#creates select input with empty choices cause it will be filled with ajax #creates select input with empty choices cause it will be filled with ajax
city = forms.ChoiceField(label='Город', choices=[('','')]) city = forms.ChoiceField(label=u'Город', choices=[('','')])
tag = forms.MultipleChoiceField(label='Теги', required=False) tag = forms.MultipleChoiceField(label=u'Теги', required=False)
periodic = forms.ChoiceField(label='Периодичность', choices=PERIODIC, required=False) periodic = forms.ChoiceField(label=u'Периодичность', choices=PERIODIC, required=False)
audience = forms.ChoiceField(label='Аудитория', choices=public, initial='', required=False) audience = forms.MultipleChoiceField(label=u'Аудитория', choices=public, initial='', required=False)
web_page = forms.CharField(label='Веб страница', required=False) web_page = forms.CharField(label=u'Веб страница', required=False)
foundation_year = forms.CharField(label='Год основания', required=False) foundation_year = forms.CharField(label=u'Год основания', required=False)
min_area = forms.CharField(label='Минимальная плошадь', required=False) members = forms.CharField(label=u'Участники', required=False)
visitors = forms.CharField(label=u'Посетители', required=False)
min_area = forms.CharField(label=u'Минимальная плошадь', required=False)
discount = forms.CharField(label=u'Cкидка(%)', required=False)
quality_label = forms.MultipleChoiceField(label=u'Метки', required=False,
choices=[('ufi', 'UFI'), ('rsva', 'РСВЯ'), ('exporating', 'ExpoRating')],
widget=forms.CheckboxSelectMultiple())
# #
currency = forms.ChoiceField(label='Валюта', choices=currencies, required=False) currency = forms.ChoiceField(label=u'Валюта', choices=currencies, required=False)
tax = forms.BooleanField(label='Налог включен', initial=True, required=False) price_day = forms.CharField(label=u'Цена за 1 день', required=False)
min_closed_area = forms.CharField(label='Минимальная цена закрытой НЕ оборудованной площади', required=False) price_all = forms.CharField(label=u'Цена за все дни', required=False)
max_closed_area = forms.CharField(label='Максимальная цена закрытой НЕ оборудованной площади', required=False) price_catalog = forms.CharField(label=u'Цена за каталог', required=False)
min_closed_equipped_area = forms.CharField(label='Минимальная цена закрытой оборудованной площади', required=False) tax = forms.BooleanField(label=u'Налог включен', initial=True, required=False)
max_closed_equipped_area = forms.CharField(label='Максимальная цена закрытой оборудованной площади', required=False) min_closed_area = forms.CharField(label=u'Минимальная цена закрытой НЕ оборудованной площади', required=False)
min_open_area = forms.CharField(label='Минимальная цена открытой площади', required=False) max_closed_area = forms.CharField(label=u'Максимальная цена закрытой НЕ оборудованной площади', required=False)
max_open_area = forms.CharField(label='Максимальная цена открытой площади', required=False) min_closed_equipped_area = forms.CharField(label=u'Минимальная цена закрытой оборудованной площади', required=False)
registration_payment = forms.CharField(label='Регистрационны взнос', required=False) max_closed_equipped_area = forms.CharField(label=u'Максимальная цена закрытой оборудованной площади', required=False)
min_open_area = forms.CharField(label=u'Минимальная цена открытой площади', required=False)
max_open_area = forms.CharField(label=u'Максимальная цена открытой площади', required=False)
registration_payment = forms.CharField(label=u'Регистрационны взнос', required=False)
expohit = forms.BooleanField(label=u'Expohit', required=False)
canceled = forms.BooleanField(label=u'Отменена', required=False)
moved = forms.BooleanField(label=u'Перенесена', required=False)
#field for comparing tmp files #field for comparing tmp files
key = forms.CharField(required=False, widget=forms.HiddenInput()) key = forms.CharField(required=False, widget=forms.HiddenInput())
# #
@ -80,21 +98,23 @@ class ExpositionCreateForm(forms.Form):
# uses enumerate for detect iteration number # uses enumerate for detect iteration number
# first iteration is a default lang so it required fields # first iteration is a default lang so it required fields
required = True if lid == 0 else False required = True if lid == 0 else False
self.fields['name_%s' % code] = forms.CharField(label='Название', required=required) self.fields['name_%s' % code] = forms.CharField(label=u'Название', required=required)
self.fields['main_title_%s' % code] = forms.CharField(label='Краткое описание', self.fields['main_title_%s' % code] = forms.CharField(label=u'Краткое описание',
required=False, widget=CKEditorWidget) required=False, widget=CKEditorWidget)
self.fields['description_%s' % code] = forms.CharField(label='Описание', self.fields['description_%s' % code] = forms.CharField(label=u'Описание',
required=False, widget=CKEditorWidget) required=False, widget=CKEditorWidget)
self.fields['time_%s' % code] = forms.CharField(label='Время работы', self.fields['time_%s' % code] = forms.CharField(label=u'Время работы',
required=False, widget=CKEditorWidget) required=False, widget=CKEditorWidget)
self.fields['products_%s' % code] = forms.CharField(label='Экспонируемые продукты', self.fields['products_%s' % code] = forms.CharField(label=u'Экспонируемые продукты',
required=False, widget=CKEditorWidget)
self.fields['discount_description_%s' % code] = forms.CharField(label=u'Описание скидки',
required=False, widget=CKEditorWidget) required=False, widget=CKEditorWidget)
#meta data #meta data
self.fields['title_%s' % code] = forms.CharField(label='Тайтл', required=required, max_length=255, self.fields['title_%s' % code] = forms.CharField(label=u'Meta title', required=False, max_length=255,
widget=forms.TextInput(attrs={'style':'width: 550px'})) widget=forms.TextInput(attrs={'style':'width: 550px'}))
self.fields['keywords_%s' % code] = forms.CharField(label='Дескрипшен', required=required, max_length=255, self.fields['keywords_%s' % code] = forms.CharField(label=u'Meta keywords', required=False, max_length=255,
widget=forms.TextInput(attrs={'style':'width: 550px'})) widget=forms.TextInput(attrs={'style':'width: 550px'}))
self.fields['descriptions_%s' % code] = forms.CharField(label='Кейвордс', required=required, max_length=255, self.fields['descriptions_%s' % code] = forms.CharField(label=u'Meta description', required=False, max_length=255,
widget=forms.TextInput(attrs={'style':'width: 550px'})) widget=forms.TextInput(attrs={'style':'width: 550px'}))
#creates select inputs ind fill it #creates select inputs ind fill it
#!service has bitfield. uncomment when country data will be filled #!service has bitfield. uncomment when country data will be filled
@ -116,18 +136,24 @@ class ExpositionCreateForm(forms.Form):
exposition = Exposition.objects.get(id=id) exposition = Exposition.objects.get(id=id)
exposition.theme.clear() exposition.theme.clear()
exposition.tag.clear() exposition.tag.clear()
exposition.organiser.clear()
exposition.company.clear()
#simple fields #simple fields
exposition.url = translit_with_separator(data['name_ru'].strip()).lower() exposition.url = translit_with_separator(data['name_ru'].strip()).lower()
exposition.data_begin = data['data_begin'] exposition.data_begin = data['data_begin']
exposition.data_end = data['data_end'] exposition.data_end = data['data_end']
exposition.periodic = data['periodic'] exposition.periodic = data['periodic']
exposition.audience = data['audience']
exposition.web_page= data['web_page'] exposition.web_page= data['web_page']
exposition.foundation_year = data['foundation_year'] exposition.foundation_year = data['foundation_year']
exposition.members = data['members']
exposition.visitors = data['visitors']
exposition.min_area = data['min_area'] exposition.min_area = data['min_area']
# #
exposition.currency = data['currency'] exposition.currency = data['currency']
exposition.price_day = data['price_day']
exposition.price_all = data['price_all']
exposition.price_catalog = data['price_catalog']
exposition.tax = data['tax'] exposition.tax = data['tax']
exposition.min_closed_area = data['min_closed_area'] exposition.min_closed_area = data['min_closed_area']
exposition.max_closed_area = data['max_closed_area'] exposition.max_closed_area = data['max_closed_area']
@ -137,6 +163,23 @@ class ExpositionCreateForm(forms.Form):
exposition.max_open_area = data['max_open_area'] exposition.max_open_area = data['max_open_area']
exposition.registration_payment = data['registration_payment'] exposition.registration_payment = data['registration_payment']
exposition.discount = data['discount']
exposition.expohit = data['expohit']
exposition.canceled = data['canceled']
exposition.moved = data['moved']
# generates bitfield
quality = 0
if data['quality_label']:
quality = reduce(lambda x,y: x|y, (getattr(Exposition.quality_label, item) for item in data['quality_label']))
exposition.quality_label = quality
audience = 0
if data['audience']:
audience = reduce(lambda x,y: x|y, (getattr(Exposition.audience, item) for item in data['audience']))
exposition.audience = audience
if data.get('country'): if data.get('country'):
exposition.country = Country.objects.get(id=data['country'].id)#.id cause select uses queryset exposition.country = Country.objects.get(id=data['country'].id)#.id cause select uses queryset
@ -156,10 +199,18 @@ class ExpositionCreateForm(forms.Form):
for item in data['tag']: for item in data['tag']:
exposition.tag.add(item) exposition.tag.add(item)
# uses because in the next loop data will be overwritten # uses because in the next loop data will be overwritten
for item in data['organiser']:
exposition.organiser.add(item)
for item in data['company']:
exposition.company.add(item)
exposition.save() exposition.save()
#save files # save files
check_tmp_files(exposition, data['key']) check_tmp_files(exposition, data.get('key'))
check_tmp_timetables(exposition, data.get('key'))
return exposition
def clean(self): def clean(self):
id = self.cleaned_data.get('exposition_id') id = self.cleaned_data.get('exposition_id')
@ -180,14 +231,14 @@ class ExpositionCreateForm(forms.Form):
cleaned_data = super(ExpositionCreateForm, self).clean() cleaned_data = super(ExpositionCreateForm, self).clean()
web_page = cleaned_data.get('web_page') web_page = cleaned_data.get('web_page')
if not web_page: if not web_page:
return web_page return ''
import socket validate = URLValidator()
try: try:
socket.getaddrinfo(web_page, 80) validate(web_page)
return web_page except(forms.ValidationError),e:
except: raise forms.ValidationError(e.messages[0])
raise forms.ValidationError('Введите правильный адрес страници') return web_page
def clean_foundation_year(self): def clean_foundation_year(self):
""" """
@ -197,6 +248,47 @@ class ExpositionCreateForm(forms.Form):
foundation_year = cleaned_data.get('foundation_year').strip() foundation_year = cleaned_data.get('foundation_year').strip()
return is_positive_integer(foundation_year) return is_positive_integer(foundation_year)
def clean_price_day(self):
"""
checking price_day
"""
cleaned_data = super(ExpositionCreateForm, self).clean()
price_day = cleaned_data.get('price_day').strip()
return is_positive_integer(price_day)
def clean_price_all(self):
"""
checking price_all
"""
cleaned_data = super(ExpositionCreateForm, self).clean()
price_all = cleaned_data.get('price_all').strip()
return is_positive_integer(price_all)
def clean_price_catalog(self):
"""
checking price_catalog
"""
cleaned_data = super(ExpositionCreateForm, self).clean()
price_catalog = cleaned_data.get('price_catalog').strip()
return is_positive_integer(price_catalog)
def clean_visitors(self):
"""
checking visitors
"""
cleaned_data = super(ExpositionCreateForm, self).clean()
visitors = cleaned_data.get('visitors').strip()
return is_positive_integer(visitors)
def clean_members(self):
"""
checking members
"""
cleaned_data = super(ExpositionCreateForm, self).clean()
members = cleaned_data.get('members').strip()
return is_positive_integer(members)
def clean_min_area(self): def clean_min_area(self):
""" """
checking min_area checking min_area
@ -262,17 +354,13 @@ class ExpositionCreateForm(forms.Form):
registration_payment = cleaned_data.get('registration_payment').strip() registration_payment = cleaned_data.get('registration_payment').strip()
return is_positive_integer(registration_payment) return is_positive_integer(registration_payment)
def clean_discount(self):
"""
checking discount
class ExpositionChangeForm(ExpositionCreateForm): """
""" cleaned_data = super(ExpositionCreateForm, self).clean()
add some fields to ExpositionCreateForm discount = cleaned_data.get('discount').strip()
""" return is_positive_integer(discount)
organiser = forms.ModelMultipleChoiceField(label='Организаторы', queryset=Organiser.objects.all(), required=False)
company = forms.ModelMultipleChoiceField(label='Компании', queryset=Company.objects.all(), required=False)
users = forms.ModelMultipleChoiceField(label='Пользователи', queryset=User.objects.all(), required=False)
class ExpositionDeleteForm(forms.ModelForm): class ExpositionDeleteForm(forms.ModelForm):
url = forms.CharField(widget=forms.HiddenInput()) url = forms.CharField(widget=forms.HiddenInput())
@ -282,9 +370,39 @@ class ExpositionDeleteForm(forms.ModelForm):
fields = ('url',) fields = ('url',)
class StatisticForm(forms.ModelForm):
year = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}))
visitors = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False)
members = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False)
class Meta:
model = Statistic
exclude = ('exposition')
def clean_year(self):
cleaned_data = super(StatisticForm, self).clean()
year = cleaned_data.get('year').strip()
return is_positive_integer(year)
def clean_members(self):
cleaned_data = super(StatisticForm, self).clean()
members = cleaned_data.get('members').strip()
return is_positive_integer(members)
def clean_visitors(self):
cleaned_data = super(StatisticForm, self).clean()
visitors = cleaned_data.get('visitors').strip()
return is_positive_integer(visitors)
from functions.files import check_tmp_timetables
class TimeTableForm(forms.Form): class TimeTableForm(forms.Form):
begin = forms.DateTimeField(label='Время начала', widget=forms.TextInput(attrs={'style':'width: 150px'})) begin = forms.DateTimeField(label='Время начала', input_formats=date_formats,
end = forms.DateTimeField(label='Время окончания', widget=forms.TextInput(attrs={'style':'width: 150px'})) widget=forms.TextInput(attrs={'style':'width: 150px'}))
end = forms.DateTimeField(label='Время окончания', input_formats=date_formats,
widget=forms.TextInput(attrs={'style':'width: 150px'}))
timetable_organiser = forms.ModelChoiceField(label='Организатор', queryset=Organiser.objects.all(), empty_label='', required=False)
# uses for comparing with TmpTimetable key
key = forms.CharField(required=False, widget=forms.HiddenInput())
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
""" """
@ -299,7 +417,29 @@ class TimeTableForm(forms.Form):
# uses enumerate for detect iteration number # uses enumerate for detect iteration number
# first iteration is a default lang so it required fields # first iteration is a default lang so it required fields
required = True if lid == 0 else False required = True if lid == 0 else False
self.fields['name_%s' % code] = forms.CharField(label='Название', required=required) self.fields['programe_%s' % code] = forms.CharField(label='Программа', required=required,
widget=TinyMCE())
self.fields['speaker_%s' % code] = forms.CharField(label='Спикеры', required=False,
widget=forms.TextInput(attrs={'style':'width: 550px'}))
def save(self, id=None): def save(self,exposition=None):
pass data = self.cleaned_data
if not exposition:
timetable = TmpTimeTable()
timetable.key = data.get('key')
else:
timetable = TimeTable()
# simple fields
if data.get('timetable_organiser'):
timetable.timetable_organiser = data['timetable_organiser']
timetable.exposition = exposition
timetable.begin = data.get('begin')
timetable.end = data.get('end')
if not exposition:
fill_with_signal(TmpTimeTable, timetable, data)
else:
fill_with_signal(TimeTable, timetable, data)
return timetable

@ -1,39 +1,55 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
from django.db.models.signals import post_save, pre_save
from django.utils.translation import ugettext as _
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
import copy import copy, datetime
from django.contrib.contenttypes import generic
from bitfield import BitField
from service.models import Service
from functions.db import db_table_exists
from organiser.models import Organiser
# #
from functions.custom_fields import EnumField from functions.custom_fields import EnumField
from functions.signal_handlers import post_save_handler, pre_save_handler
from functions.models_methods import ExpoManager
from functions.model_mixin import EventMixin
AUDIENCE1 = ((None,'Не выбрано'), AUDIENCE1 = ((None,_(u'Не выбрано')),
('experts', 'Специалисты'), ('experts', _(u'Специалисты')),
('experts and consumers', 'Специалисты и потребители'), ('experts and consumers', _(u'Специалисты и потребители')),
('general public', 'Широкая публика')) ('general public', _(u'Широкая публика'))
)
AUDIENCE = (None,'experts', 'experts and consumers', 'general public') AUDIENCE = (None,'experts', 'experts and consumers', 'general public')
BIT_AUDIENCE = (('experts', _(u'Специалисты')), ('experts and consumers', _(u'Специалисты и потребители')),
('general public', _(u'Широкая публика')))
CURRENCY = ('RUB', 'USD', 'EUR') CURRENCY = ('RUB', 'USD', 'EUR')
# check if table exist and create flags if true
flags = [str(item.id) for item in Service.objects.all()] if db_table_exists('service_service') else []
class ExpositionManager(TranslationManager):
def safe_get(self, **kwargs):
model = self.model
try:
return model.objects.get(**kwargs)
except:
return None
class Exposition(TranslatableModel): class Exposition(TranslatableModel, EventMixin):
""" """
Create Exposition model Create Exposition model
Uses hvad.TranslatableModel which is child of django.db.models class Uses hvad.TranslatableModel which is child of django.db.models class
""" """
#set manager of this model #set manager of this model
objects = ExpositionManager() objects = ExpoManager()
url = models.SlugField(unique=True) url = models.SlugField(unique=True)
data_begin = models.DateField(verbose_name='Дата начала') data_begin = models.DateField(verbose_name='Дата начала')
data_end = models.DateField(verbose_name='Дата окончания') data_end = models.DateField(verbose_name='Дата окончания')
#relations
services = BitField(flags=flags)
quality_label = BitField(flags=['ufi', 'rsva', 'exporating'])
audience = BitField(flags=[k for k, v in BIT_AUDIENCE])
# relations
country = models.ForeignKey('country.Country', verbose_name='Страна', on_delete=models.PROTECT) country = models.ForeignKey('country.Country', verbose_name='Страна', on_delete=models.PROTECT)
city = models.ForeignKey('city.City', verbose_name='Город', on_delete=models.PROTECT) city = models.ForeignKey('city.City', verbose_name='Город', on_delete=models.PROTECT)
place = models.ForeignKey('place_exposition.PlaceExposition', verbose_name='Место проведения', place = models.ForeignKey('place_exposition.PlaceExposition', verbose_name='Место проведения',
@ -45,18 +61,20 @@ class Exposition(TranslatableModel):
organiser = models.ManyToManyField('organiser.Organiser', verbose_name='Организатор', organiser = models.ManyToManyField('organiser.Organiser', verbose_name='Организатор',
blank=True, null=True, related_name='exposition_organisers') blank=True, null=True, related_name='exposition_organisers')
company = models.ManyToManyField('company.Company', verbose_name='Компании', company = models.ManyToManyField('company.Company', verbose_name='Компании',
blank=True, null=True, related_name='exposition_compamies') blank=True, null=True, related_name='exposition_companies')
users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки', users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки',
blank=True, null=True, related_name='exposition_users') blank=True, null=True, related_name='exposition_users')
#service = models.ManyToManyField('service.Service', verbose_name='Услуги',
# blank=True, null=True, related_name='exposition_services')
periodic = models.FloatField(verbose_name='Переодичность', blank=True, null=True) periodic = models.FloatField(verbose_name='Переодичность', blank=True, null=True)
audience = EnumField(values=AUDIENCE, blank=True) #audience = EnumField(values=AUDIENCE, blank=True)
web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True) web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True)
foundation_year = models.PositiveIntegerField(verbose_name='Год основания', blank=True, null=True)
min_area = models.PositiveIntegerField(verbose_name='Минимальная площадь', blank=True, null=True) min_area = models.PositiveIntegerField(verbose_name='Минимальная площадь', blank=True, null=True)
# #
currency = EnumField(values=CURRENCY, default='RUB') currency = EnumField(values=CURRENCY, default='RUB')
price_day = models.PositiveIntegerField(verbose_name='Стоимость билета 1 день', blank=True, null=True)
price_all = models.PositiveIntegerField(verbose_name='Стоимость билета все дни', blank=True, null=True)
price_catalog = models.PositiveIntegerField(verbose_name='Стоимость каталога', blank=True, null=True)
tax = models.BooleanField(verbose_name='Налог', default=1) tax = models.BooleanField(verbose_name='Налог', default=1)
min_closed_area = models.PositiveIntegerField(verbose_name='Минимальная цена закрытой НЕ оборудованной площади', min_closed_area = models.PositiveIntegerField(verbose_name='Минимальная цена закрытой НЕ оборудованной площади',
blank=True, null=True) blank=True, null=True)
@ -72,44 +90,83 @@ class Exposition(TranslatableModel):
blank=True, null=True) blank=True, null=True)
registration_payment = models.PositiveIntegerField(verbose_name='Регистрационный взнос', blank=True, null=True) registration_payment = models.PositiveIntegerField(verbose_name='Регистрационный взнос', blank=True, null=True)
discount = models.PositiveIntegerField(verbose_name='Скидка', blank=True, null=True)
expohit = models.BooleanField(verbose_name='Expohit', default=0)
#administrator can cancel exposition #administrator can cancel exposition
canceled_by_administrator = models.BooleanField(default=0) canceled_by_administrator = models.BooleanField(default=0)
#can publish not immediately #can publish not immediately
is_published = models.BooleanField(default=0) is_published = models.BooleanField(default=0)
canceled = models.BooleanField(default=0)
moved = models.BooleanField(default=0)
files = generic.GenericRelation('file.FileModel', content_type_field='content_type', object_id_field='object_id')
# statistic
foundation_year = models.PositiveIntegerField(verbose_name='Год основания', blank=True, null=True)
visitors = models.PositiveIntegerField(verbose_name='Посетители', blank=True, null=True)
members = models.PositiveIntegerField(verbose_name='Участники', blank=True, null=True)
translations = TranslatedFields( translations = TranslatedFields(
name = models.CharField(verbose_name='Название', max_length=255), name = models.CharField(verbose_name='Название', max_length=255),
main_title = models.TextField(verbose_name='Краткое описание', blank=True), main_title = models.TextField(verbose_name='Краткое описание', blank=True),
description = models.TextField(verbose_name='Описание', blank=True), description = models.TextField(verbose_name='Описание', blank=True),
products = models.TextField(verbose_name='Экспонируемые продукты', blank=True), products = models.TextField(verbose_name='Экспонируемые продукты', blank=True),
discount_description = models.TextField(verbose_name='Описание скидки', blank=True),
time = models.TextField(verbose_name='Время работы', blank=True), time = models.TextField(verbose_name='Время работы', blank=True),
#-----meta data #-----meta data
title = models.CharField(max_length=250), title = models.CharField(max_length=250),
descriptions = models.CharField(max_length=250), descriptions = models.CharField(max_length=250),
keywords = models.CharField(max_length=250), keywords = models.CharField(max_length=250),
) )
#field saves information about creating and changing model # field saves information about creating and changing model
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
#mark views = models.PositiveIntegerField(null=True, default=0)
def __unicode__(self): def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk)) return self.lazy_translation_getter('name', unicode(self.pk))
def cancel(self): def get_audience(self):
self.canceled_by_administrator = True checked = [item for item, bool in self.audience if bool==True]
audience = []
for k, v in BIT_AUDIENCE:
for item in checked:
if item == k:
audience.append(v)
return ', '.join(audience)
def get_periodic(self):
periodic = {0: '', 1.0: _(u'Ежегодно'), 2.0: _(u'2 раза в год'), 3.0: _(u'3 раза в год'),
4.0: _(u'4 раза в год'), 5.0: _(u'5 раз в год'), 0.5: _(u'Раз в 2 года'),
0.33: _(u'Раз в 3 года'), 0.25: _(u'Раз в 4 года')}
return periodic.get(self.periodic)
def get_nearest_events(self):
theme = self.theme.all()[0]
now = datetime.datetime.now()
now = now.replace(day=now.day-1)
expositions = Exposition.objects.filter(theme__in=[theme], data_begin__gt=now).exclude(id=self.id)
return expositions[3:]
def get_catalog_url(self):
return '/expositions/'
def get_event_type(self):
return _(u'Выставки')
def get_calendar_url(self):
return '/exposition-add-calendar/%s/'%self.id
def get_visit_url(self):
return '/exposition-visit/%s/'%self.id
def on(self):
self.is_published = True
self.canceled_by_administrator = False
self.save()
def off(self):
self.is_published = False
self.canceled_by_administrator = True
self.save()
def clone(self): def clone(self):
""" """
@ -131,6 +188,16 @@ class Exposition(TranslatableModel):
duplicate.is_published = False duplicate.is_published = False
duplicate.cancel_by_administrator = False duplicate.cancel_by_administrator = False
ignore_fields = ['id', 'master', 'language_code']
duplicate.translate('ru')
tr = self._meta.translations_model.objects.get(language_code = 'ru',master__id=self.pk)
for field in duplicate._translated_field_names:
if field in ignore_fields:
continue
setattr(duplicate, field, getattr(tr, field))
duplicate.save() duplicate.save()
# but lost all ManyToMany relations and Translations. # but lost all ManyToMany relations and Translations.
@ -141,24 +208,17 @@ class Exposition(TranslatableModel):
for item in source.all(): for item in source.all():
destination.add(item) destination.add(item)
# copy translations return duplicate
languages = self.get_available_languages()
ignore_fields = ['id', 'master', 'language_code']
for code in languages:
duplicate.translate(code)
tr = self._meta.translations_model.objects.get(language_code = code,master__id=self.pk)
for field in duplicate._translated_field_names:
if field in ignore_fields:
continue
setattr(duplicate, field, getattr(tr, field))
duplicate.save()
return duplicate class Statistic(models.Model):
exposition = models.ForeignKey(Exposition, related_name='statistic')
year = models.PositiveIntegerField(verbose_name='Год')
members = models.PositiveIntegerField(verbose_name='Посетители')
visitors = models.PositiveIntegerField(verbose_name='Участники')
from django.core import serializers
from functions.models_methods import hvad_to_dict
class TimeTable(TranslatableModel): class TimeTable(TranslatableModel):
""" """
@ -168,7 +228,64 @@ class TimeTable(TranslatableModel):
exposition = models.ForeignKey(Exposition, related_name='business_program') exposition = models.ForeignKey(Exposition, related_name='business_program')
begin = models.DateTimeField(verbose_name='Начало') begin = models.DateTimeField(verbose_name='Начало')
end = models.DateTimeField(verbose_name='Конец') end = models.DateTimeField(verbose_name='Конец')
timetable_organiser = models.ForeignKey(Organiser, null=True, blank=True)
#
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
#translated fields #translated fields
translations = TranslatedFields( translations = TranslatedFields(
name = models.CharField(verbose_name='Название', max_length=255) programe = models.TextField(verbose_name='Программа'),
) speaker = models.CharField(verbose_name='Спикеры', max_length=255, blank=True)
)
def to_dict(self):
#obj = serializers.serialize('json', [self,])
return hvad_to_dict(self)
class TmpTimeTable(TranslatableModel):
exposition = models.ForeignKey(Exposition, null=True, blank=True)
begin = models.DateTimeField(verbose_name='Начало')
end = models.DateTimeField(verbose_name='Конец')
timetable_organiser = models.ForeignKey(Organiser, null=True, blank=True)
# key uses for checking keys from new objects.
key = models.CharField(max_length=255, blank=True)
#
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
#translated fields
translations = TranslatedFields(
programe = models.TextField(verbose_name='Программа'),
speaker = models.CharField(verbose_name='Спикеры', max_length=255, blank=True)
)
def clone(self, exposition=None):
"""
Return an identical copy of the instance with a new ID.
"""
if not self.pk:
raise ValueError('Instance must be saved before it can be cloned.')
duplicate = copy.copy(self)
# Setting pk to None. Django thinking this is a new object.
duplicate.pk = None
duplicate.exposition = exposition
ignore_fields = ['id', 'master', 'language_code']
duplicate.translate('ru')
tr = self._meta.translations_model.objects.get(language_code = 'ru',master__id=self.pk)
for field in duplicate._translated_field_names:
if field in ignore_fields:
continue
setattr(duplicate, field, getattr(tr, field))
duplicate.save()
return duplicate
pre_save.connect(pre_save_handler, sender=Exposition)
post_save.connect(post_save_handler, sender=Exposition)
post_save.connect(post_save_handler, sender=TimeTable)
post_save.connect(post_save_handler, sender=TmpTimeTable)

@ -0,0 +1,15 @@
"""
from haystack import indexes
from models import Exposition
class ExpositionIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True)
def get_model(self):
return Exposition
def index_queryset(self, using=None):
return self.get_model().objects.filter()
"""

@ -3,4 +3,4 @@ from django.db.models.signals import post_save
from models import Exposition from models import Exposition
from functions.signal_handlers import post_save_handler from functions.signal_handlers import post_save_handler
post_save.connect(post_save_handler, sender=Exposition) #post_save.connect(post_save_handler, sender=Exposition)

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from views import ExpositionView, ExpositionVisitors, ExpositionMembers
urlpatterns = patterns('',
url(r'expositions/(?P<params>.*)/(?P<page>\d+)/$', ExpositionView.as_view()),
url(r'expositions/(?P<page>\d+)/$', ExpositionView.as_view()),
url(r'expositions/(?P<params>.*)/visitors/$', ExpositionVisitors.as_view()),
url(r'expositions/(?P<params>.*)/members/$', ExpositionMembers.as_view()),
url(r'expositions/(?P<params>.*)/$', ExpositionView.as_view()),
url(r'expositions/$', ExpositionView.as_view()),
#
url(r'exposition-add-calendar/(?P<id>\d+)/$', 'exposition.views.exposition_add_calendar'),
url(r'exposition-remove-calendar/(?P<id>\d+)/$', 'exposition.views.exposition_remove_calendar'),
url(r'exposition-visit/(?P<id>\d+)/$', 'exposition.views.exposition_visit'),
url(r'exposition-unvisit/(?P<id>\d+)/$', 'exposition.views.exposition_unvisit'),
)

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.template import RequestContext
from django.shortcuts import get_object_or_404
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
#models
from models import Exposition
from accounts.models import User
from functions.custom_views import ExpoListView, ExpoMixin
from django.views.generic import ListView
#
import json
from django.utils.translation import ugettext as _
class ExpositionView(ExpoListView):
model = Exposition
template_name = 'event_catalog.html'
class ExpositionVisitors(ExpositionView):
model = Exposition
template_name = 'event_visitors.html'
def get_queryset(self):
params = self.get_params()
for param in params:
if param.get('type') == 'event':
exp = Exposition.objects.safe_get(url=param.get('url'))
#query = exp.users
param['name'] = exp.name
params.append({'type':'visitors', 'name':_(u'Посетители')})
self.params = params
return exp.users.all()
class ExpositionMembers(ExpoListView):
model = Exposition
template_name = 'event_members.html'
def get_queryset(self):
params = self.get_params()
for param in params:
if param.get('type') == 'event':
exp = Exposition.objects.safe_get(url=param.get('url'))
param['name'] = exp.name
#query = exp.users
params.append({'type':'members', 'name':_(u'Участники')})
self.params = params
return exp.company.all()
def exposition_add_calendar(request, id):
args = {'success': False}
user = request.user
if user.is_authenticated():
exp = Exposition.objects.safe_get(id=id)
if exp:
user.calendar.expositions.add(exp)
args['success'] = True
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')
def exposition_remove_calendar(request, id):
args = {'success': False}
user = request.user
if user.is_authenticated():
exp = Exposition.objects.safe_get(id=id)
if exp:
user.calendar.expositions.remove(exp)
args['success'] = True
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')
def exposition_visit(request, id):
args = {'success': False}
user = request.user
if user.is_authenticated():
exp = Exposition.objects.safe_get(id=id)
if exp:
exp.users.add(user)
args['success'] = True
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')
def exposition_unvisit(request, id):
args = {'success': False}
user = request.user
if user.is_authenticated():
exp = Exposition.objects.safe_get(id=id)
if exp:
exp.users.remove(user)
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')

@ -40,7 +40,7 @@ class FileModelForm(forms.Form):
# using enumerate for detect iteration number # using enumerate for detect iteration number
# first iteration is a default lang so it required fields # first iteration is a default lang so it required fields
required = True if lid == 0 else False required = True if lid == 0 else False
self.fields['file_name_%s'%code] = forms.CharField(label='Имя файла',required=required, widget=forms.TextInput(attrs={'placeholder': 'Имя'})) self.fields['file_name_%s'%code] = forms.CharField(label='Имя файла',required=False, widget=forms.TextInput(attrs={'placeholder': 'Имя'}))
self.fields['description_%s'%code] = forms.CharField(label='Описание', required=False, widget=CKEditorWidget()) self.fields['description_%s'%code] = forms.CharField(label='Описание', required=False, widget=CKEditorWidget())
def save(self, request, obj=None): def save(self, request, obj=None):

@ -95,7 +95,7 @@ class TmpFile(TranslatableModel):
img_width = models.PositiveIntegerField(blank=True, null=True) img_width = models.PositiveIntegerField(blank=True, null=True)
img_height = models.PositiveIntegerField(blank=True, null=True) img_height = models.PositiveIntegerField(blank=True, null=True)
#key uses for checking keys from new objects. # key uses for checking keys from new objects.
# (if keys the same as in form move Tmpfile to FileModel) # (if keys the same as in form move Tmpfile to FileModel)
key = models.CharField(max_length=255, blank=True) key = models.CharField(max_length=255, blank=True)
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)

@ -1,3 +1,4 @@
import datetime
#https://djangosnippets.org/snippets/2607/ #https://djangosnippets.org/snippets/2607/
def required(wrapping_functions,patterns_rslt): def required(wrapping_functions,patterns_rslt):
''' '''
@ -50,4 +51,5 @@ def _wrap_instance__resolve(wrapping_functions,instance):
return instance return instance
#----------------------------- #-----------------------------
datetime_handler = lambda obj: (obj.isoformat() if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date) else None)

@ -5,6 +5,7 @@ from django.core import exceptions
from django import forms from django import forms
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.conf import settings from django.conf import settings
from south.modelsinspector import add_introspection_rules
try: try:
import json import json
except: except:
@ -15,6 +16,8 @@ FILE_TYPES = ('PDF', 'DOC', 'TXT', 'OTHER')
IMG_TYPES = ('JPG', 'BMP', 'PNG', 'GIF',) IMG_TYPES = ('JPG', 'BMP', 'PNG', 'GIF',)
PURPOSES = ('photo', 'flat') PURPOSES = ('photo', 'flat')
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^functions\.custom_fields\.EnumField", "^functions\.custom_fields\.LocationField"])
class EnumField(models.Field): class EnumField(models.Field):

@ -1,30 +1,34 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect, HttpResponse
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.conf import settings from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.admin.views.decorators import staff_member_required from django.contrib.admin.views.decorators import staff_member_required
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage, InvalidPage
from django.db.models.deletion import ProtectedError from django.db.models.deletion import ProtectedError
#forms and models #forms and models
from file.forms import FileModelForm from file.forms import FileModelForm
from file.models import TmpFile from file.models import TmpFile
from theme.models import Tag from theme.models import Tag
from accounts.models import User
from functions.forms import AdminSearchForm
from django.utils.translation import get_language as lang
from hvad.utils import get_translation_aware_manager
#python #python
import random import random
from country.models import Country
@staff_member_required
def objects_list(request, Model, template, item_per_page=10): @login_required
def filtered_list(request, objects, template, item_per_page=20):
""" """
Return template with all objects of model Model Return template with objects in it with pagination
Model - objects Model
item_per_page - how many objects view in the one page item_per_page - how many objects view in the one page
""" """
list = Model.objects.all() paginator = Paginator(objects, item_per_page)
paginator = Paginator(list, item_per_page)
page = request.GET.get('page') page = request.GET.get('page')
try: try:
objects = paginator.page(page) objects = paginator.page(page)
@ -34,16 +38,33 @@ def objects_list(request, Model, template, item_per_page=10):
except EmptyPage: except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results. # If page is out of range (e.g. 9999), deliver last page of results.
objects = paginator.page(paginator._num_pages) objects = paginator.page(paginator._num_pages)
return render_to_response(template, {'objects': objects}) return render_to_response(template, {'objects': objects, 'search_form': AdminSearchForm()})
@login_required from django.db.models.loading import get_model
def filtered_list(request, objects, template, item_per_page=10): from theme.models import Theme
@staff_member_required
def objects_list(request, Model, template, item_per_page=20):
""" """
Return template with objects in it with pagination Return template with all objects of model Model
Model - objects Model
item_per_page - how many objects view in the one page item_per_page - how many objects view in the one page
""" """
paginator = Paginator(objects, item_per_page)
if request.GET:
form = AdminSearchForm(request.POST)
if form.is_valid():
s_name = request.GET.get('search_name')
if s_name:
objects = get_translation_aware_manager(Model).filter(name__contains=s_name).distinct()
return filtered_list(request, objects, template, 1000)
else:
list = Model.objects.all()
else:
list = Model.objects.all()
paginator = Paginator(list, item_per_page)
page = request.GET.get('page') page = request.GET.get('page')
try: try:
objects = paginator.page(page) objects = paginator.page(page)
@ -53,8 +74,7 @@ def filtered_list(request, objects, template, item_per_page=10):
except EmptyPage: except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results. # If page is out of range (e.g. 9999), deliver last page of results.
objects = paginator.page(paginator._num_pages) objects = paginator.page(paginator._num_pages)
return render_to_response(template, {'objects': objects}) return render_to_response(template, {'objects': objects, 'search_form': AdminSearchForm()})
@login_required @login_required
def add_object(request, Form, template_string, redirect_string, #required values def add_object(request, Form, template_string, redirect_string, #required values
@ -163,4 +183,108 @@ def delete_object(request, Model, Form, url, prev_page,):
args['object'] = object args['object'] = object
args['prev_page'] = prev_page args['prev_page'] = prev_page
return render_to_response('delete.html', args) return render_to_response('delete.html', args)
#-----class------------------
from django.views.generic import ListView
from functions.views_help import split_params
from city.models import City
from exposition.models import Exposition
from conference.models import Conference
from seminar.models import Seminar
from webinar.models import Webinar
from company.models import Company
from django.utils.translation import ugettext as _
class ExpoMixin(object):
def get_params(self):
model_names = {Exposition: _(u'Выставки'), Conference: _(u'Конференции'),
Seminar: _(u'Семинары'),Webinar: _(u'Вебинары'), Company: _(u'Участники')}
model_alternative_name = {Exposition: 'exposition', Conference: 'conference'}
params = [{'type':'model', 'url':self.model, 'name': model_names.get(self.model),
'alternative_name': model_alternative_name.get(self.model)}]
st = self.kwargs.get('params')
if st:
params = params + split_params(st)
return params
single_page_filter = {Exposition:'event', Conference:'event', Seminar:'event', Webinar:'event', Company:'member',
User:'visitor'}
class ExpoListView(ExpoMixin, ListView):
"""
"""
paginate_by = 2
params = None
single_page = False
def get_queryset(self):
query = self.model.objects.all()
params = self.get_params()
for param in params:
if param.get('type') == 'country':
country = Country.objects.safe_get(url=param.get('url'))
if country:
param['name'] = country.name
query = query.filter(country=country)
if param.get('type') == 'city':
city = City.objects.safe_get(url=param.get('url'))
if city:
param['name'] = city.name
query = query.filter(city=city)
if param.get('type') == 'theme':
theme = Theme.objects.safe_get(url=param.get('url'))
if theme:
param['name'] = theme.name
query = query.filter(theme=theme)
if param.get('type') == 'tag':
tag = Tag.objects.safe_get(url=param.get('url'))
if tag:
param['name'] = tag.name
query = query.filter(tag=tag)
if param.get('type') == 'year':
param['name'] = param.get('url')
query = query.filter(data_begin__year=param.get('url'))
if param.get('type') == 'month':
monthes = {'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4, 'may': 5, 'jun': 6,
'jul': 7, 'aug': 8, 'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12}
param['name'] = param.get('url')
query = query.filter(data_begin__month=monthes.get(param.get('url')))
if param.get('type') == 'member' and self.model != Company:
param['name'] = param.get('url')
company = Company.objects.safe_get(url=param.get('url'))
if company:
param['name'] = company.name
query = query.filter(company__in=[company])
if param.get('type') == single_page_filter.get(self.model):
query = query.filter(url=param.get('url'))
if query:
self.single_page = True
param['name'] = query[0].name
#if self.request:
# views = query[0].views
# query.update(views=views+1)
self.params = params
return query
def get_context_data(self, **kwargs):
context = super(ExpoListView, self).get_context_data(**kwargs)
context['filter'] = self.params
context['single_page'] = self.single_page
return context

@ -91,4 +91,32 @@ def check_tmp_files(object, key=None):
file_obj.description = trans_object.description file_obj.description = trans_object.description
file_obj.save() file_obj.save()
list.delete() list.delete()
from exposition.models import TmpTimeTable, TimeTable
from functions.translate import fill_with_signal
def check_tmp_timetables(object, key=None):
"""
object - exposition to which we saved timetable
"""
if key:
temp_objects = TmpTimeTable.objects.filter(key=key)
for obj in temp_objects:
timetable = TimeTable(begin=obj.begin, end=obj.end, exposition=object,
timetable_organiser=obj.timetable_organiser)
data = {}
for code, name in settings.LANGUAGES:
#timetable.translate(code)
trans_object = TmpTimeTable._meta.translations_model.objects.get(language_code = code,master__id=getattr(obj,'id'))
data['programe_%s'%code] = trans_object.programe
data['speaker_%s'%code] = trans_object.speaker
fill_with_signal(TimeTable, timetable, data)
temp_objects.delete()
else:
pass

@ -21,7 +21,9 @@ def translit_with_separator(string, separator='-'):
usage: translit_with_separator('введите, слово', '_') return 'vvedite_slovo' usage: translit_with_separator('введите, слово', '_') return 'vvedite_slovo'
""" """
string = string.strip()
#make string unicode #make string unicode
string = u'%s'%string string = u'%s'%string
#make string translit #make string translit
st = pytils.translit.translify(string) st = pytils.translit.translify(string)

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from django import forms
from django.utils.translation import ugettext_lazy as _
from theme.models import Theme
class AdminSearchForm(forms.Form):
search_name = forms.CharField(required=False, max_length=50)
class ThemeSearch(forms.Form):
event = forms.MultipleChoiceField(required=False,widget=forms.CheckboxSelectMultiple, choices=[(0, _(u'выставки')),
(1, _(u'конференции')),
(2, _(u'семинары')),
(3, _(u'вебинары'))])
theme = forms.ModelMultipleChoiceField(required=False, queryset=Theme.objects.all(),
widget=forms.CheckboxSelectMultiple)

@ -0,0 +1,61 @@
from service.models import Service
class ExpoMixin(object):
def get_logo(self):
logo = self.files.filter(purpose='logo')
if logo:
return logo[0]
return logo
def get_preview(self):
preview = self.files.filter(purpose='preview')
if preview:
return preview[0]
return preview
def get_photos(self):
photos = self.files.filter(purpose='photo')
return photos
class EventMixin(object):
def get_permanent_url(self):
url = '%sevent-%s'%(self.get_catalog_url(), self.url)
return url
def get_logo(self):
logo = self.files.filter(purpose='logo')
if logo:
return logo[0]
return logo
def get_preview(self):
preview = self.files.filter(purpose='preview')
if preview:
return preview[0]
return preview
def get_photos(self):
photos = self.files.filter(purpose='photo')
return photos
def on(self):
self.is_published = True
self.canceled_by_administrator = False
self.save()
def off(self):
self.is_published = False
self.canceled_by_administrator = True
self.save()
def cancel(self):
self.canceled_by_administrator = True
def get_services(self):
ids = [item for item, bool in self.services if bool==True]
return [Service.objects.get(id=id) for id in ids]

@ -0,0 +1,27 @@
from django.utils.translation import get_language
from hvad.models import TranslationManager
class ExpoManager(TranslationManager):
def all(self, lang=None):
if lang:
return super(ExpoManager, self).language(lang).all().order_by('name')
else:
return super(ExpoManager, self).language(get_language()).all().order_by('name')
def safe_get(self, **kwargs):
model = self.model
try:
return model.objects.get(**kwargs)
except:
return None
def hvad_to_dict(object):
"""
"""
value = object.__dict__
lang = get_language()
bad_fields = ['master_id', 'id', 'language_code']
value.update({key:value for key, value in object.translations.filter(language_code=lang).values()[0].iteritems() if key not in bad_fields})
return value

@ -45,6 +45,7 @@ def fill_meta_information(obj):
# get Setting model object # get Setting model object
setting = Setting.objects.get(key=s.get('key')) setting = Setting.objects.get(key=s.get('key'))
field = s.get('field_name') field = s.get('field_name')
if setting.type != 'transl': if setting.type != 'transl':
# simple field # simple field
if getattr(obj, field)=="": if getattr(obj, field)=="":
@ -57,5 +58,11 @@ def fill_meta_information(obj):
tr = obj._meta.translations_model.objects.get(language_code=code, master__id=getattr(obj, 'id')) tr = obj._meta.translations_model.objects.get(language_code=code, master__id=getattr(obj, 'id'))
if getattr(tr, field)=="": if getattr(tr, field)=="":
setattr(tr, field, setting.get_value(code)) value = setting.get_value(code)
try:
value = value%tr.__dict__
except KeyError:
pass
# ! charfield -> textfield
setattr(tr, field, value[:250])
tr.save() tr.save()

@ -1,7 +1,37 @@
from form_check import translit_with_separator
from signal_additional_func import fill_missing_languages, fill_meta_information from signal_additional_func import fill_missing_languages, fill_meta_information
import random, string
from functions.form_check import translit_with_separator
def pre_save_handler(sender, **kwargs):
obj = kwargs['instance']
if obj.language_code =='en':
print('bla')
try:
name = getattr(obj, 'name')
obj.url = translit_with_separator(name)
except AttributeError:
pass
if not obj.url:
obj.url = ''.join([random.choice(string.ascii_lowercase) for n in xrange(8)])
"""
url = getattr(obj, 'url')
if url:
try:
en_name = obj._meta.translations_model.objects.get(language_code='en', master__id=getattr(obj, 'id'))
obj.url = translit_with_separator(en_name)
except:
pass
else:
# generate random url if url field is empty
obj.url = ''.join([random.choice(string.ascii_lowercase) for n in xrange(8)])
"""
def post_save_handler(sender, **kwargs): def post_save_handler(sender, **kwargs):
""" """
receiver function receiver function
@ -14,7 +44,7 @@ def post_save_handler(sender, **kwargs):
fill_missing_languages(obj) fill_missing_languages(obj)
fill_meta_information(obj) fill_meta_information(obj)
from country.models import Country '''
def post_save_translation_handler(sender, **kwargs): def post_save_translation_handler(sender, **kwargs):
""" """
receiver function receiver function
@ -22,8 +52,6 @@ def post_save_translation_handler(sender, **kwargs):
""" """
obj = kwargs['instance'] obj = kwargs['instance']
if obj.language_code == 'ru': if obj.language_code == 'ru':
c = Country.objects.all()[0] obj.master.url = translit_with_separator(obj.name)
c.url = 'tttt' obj.master.save()
c.save() '''
#obj.master.url = translit_with_separator(obj.name)
#obj.master.save()

@ -9,4 +9,15 @@ def get_referer(request, default=None):
referer = re.sub('^https?:\/\/', '', referer).split('/') referer = re.sub('^https?:\/\/', '', referer).split('/')
# add the slash at the relative path's view and finished # add the slash at the relative path's view and finished
referer = u'/' + u'/'.join(referer[1:]) referer = u'/' + u'/'.join(referer[1:])
return referer return referer
def split_params(st):
st = st.split('/')
params = []
for item in st:
n = item.find('-')
if n != -1:
params.append({'type': item[:n], 'url':item[n+1:]})
return params

@ -0,0 +1,111 @@
# -*- 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
from django.db.models.loading import get_model
#
import xlwt
import xlrd
#
from import_forms import ImportEventForm, ImportThemeForm, ImportTagForm, ImportOrganiserForm,\
ImportPlaceConferenceForm, ImportPlaceExpositionForm
from export_forms import ExportEventForm, ExportOrganiserForm, ExportThemeForm, ExportTagForm,\
ExportUserForm, ExportCompanyForm, ExportPlaceConferenceForm, ExportPlaceExpositionForm
from django.views.generic import FormView
from django.contrib import messages
def xls_to_response(xls, fname):
response = HttpResponse(mimetype="application/ms-excel")
response['Content-Disposition'] = 'attachment; filename=%s' % fname
xls.save(response)
return response
class ImportView(FormView):
"""
abstract class
"""
template_name = 'import.html'
def form_valid(self, form):
form.save_file()
messages.success(self.request, 'Success')
return super(ImportView, self).form_valid(form)
class ExportView(FormView):
"""
abstract class
"""
template_name = 'export.html'
def form_valid(self, form):
workbook = form.export()
if workbook:
f_name = form.get_fname()
else:
messages.error(self.request, 'No objects found')
return HttpResponseRedirect(self.success_url)
return xls_to_response(workbook, f_name)
class ExportOrganiser(ExportView):
form_class = ExportOrganiserForm
success_url = '/admin/export-organiser'
class ExportTheme(ExportView):
form_class = ExportThemeForm
success_url = '/admin/export-theme'
class ExportTag(ExportView):
form_class = ExportTagForm
success_url = '/admin/export-tag'
class ExportUser(ExportView):
form_class = ExportUserForm
success_url = '/admin/export-user'
class ExportCompany(ExportView):
form_class = ExportCompanyForm
success_url = '/admin/export-company'
class ExportPlaceConference(ExportView):
form_class = ExportPlaceConferenceForm
success_url = '/admin/export-place_conference'
class ExportPlaceExposition(ExportView):
form_class = ExportPlaceExpositionForm
success_url = '/admin/export-place_exposition'
class ImportEvent(ImportView):
form_class = ImportEventForm
success_url = '/admin/import-event'
class ImportTheme(ImportView):
form_class = ImportThemeForm
success_url = '/admin/import-theme'
class ImportTag(ImportView):
form_class = ImportTagForm
success_url = '/admin/import-tag'
class ImportOrganiser(ImportView):
form_class = ImportOrganiserForm
success_url = '/admin/import-organiser'
class ImportPlaceExposition(ImportView):
form_class = ImportPlaceExpositionForm
success_url = '/admin/import-place_exposition'
class ImportPlaceConference(ImportView):
form_class = ImportPlaceConferenceForm
success_url = '/admin/import-place_conference'
class ExportEvent(ExportView):
form_class = ExportEventForm
template_name = 'export_event.html'
success_url = '/admin/export-event'

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
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
urlpatterns = patterns('',
url(r'^import-event/$', ImportEvent.as_view()),
url(r'^import-theme/$', ImportTheme.as_view()),
url(r'^import-tag/$', ImportTag.as_view()),
url(r'^import-organiser/$', ImportOrganiser.as_view()),
url(r'^import-place_exposition/$', ImportPlaceExposition.as_view()),
url(r'^import-place_conference/$', ImportPlaceConference.as_view()),
#
url(r'^export-event/$', ExportEvent.as_view()),
url(r'^export-theme/$', ExportTheme.as_view()),
url(r'^export-tag/$', ExportTag.as_view()),
url(r'^export-organiser/$', ExportOrganiser.as_view()),
url(r'^export-place_exposition/$', ExportPlaceExposition.as_view()),
url(r'^export-place_conference/$', ExportPlaceConference.as_view()),
url(r'^export-user/$', ExportUser.as_view()),
url(r'^export-company/$', ExportCompany.as_view()),
)

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from accounts.models import User
from country.models import Country from country.models import Country
from city.models import City from city.models import City
from theme.models import Theme, Tag from theme.models import Theme, Tag
@ -14,21 +15,24 @@ def get_int(value):
return '' return ''
return value return value
from bitfield import BitHandler
from exposition.models import BIT_AUDIENCE
def get_audience(value): def get_audience(value):
if not value: if isinstance(value, BitHandler):
return 'Не выбрано' l = [k for k, v in value.iteritems() if v]
elif value == 'experts': if l:
return 'Специалисты' new_list = []
elif value == 'experts and consumers': for value in l:
return 'Специалисты и потребители' for item1, item2 in BIT_AUDIENCE:
elif value == 'general public': if value == item1:
return 'Широкая публика' new_list.append(item2)
else:
return '' return ', '.join(new_list)
return
def get_theme(value): def get_theme(value):
objects = value.all() objects = value.all()
return ', '.join(str(obj) for obj in objects) return ','.join(str(obj.id) for obj in objects)
def get_tag(tag, theme): def get_tag(tag, theme):
@ -37,47 +41,58 @@ def get_tag(tag, theme):
result = '' result = ''
for theme in themes: for theme in themes:
# list of tags with current theme # list of tags with current theme
tag_list = [str(tag) for tag in tags if tag.theme == theme] tag_list = [str(tag.id) for tag in tags if tag.theme == theme]
result += '['+', '.join(tag_list)+']' result += '['+','.join(tag_list)+']'
return result return result
def get_place_type():
pass
field_settings = [ field_settings = [
{'name': 'id', 'verbose_name': 'id', 'type': get_int, 'width':1500}, {'name': 'id', 'verbose_name': u'id', 'type': get_int, 'width':1500},
{'name': 'url', 'verbose_name': 'url', 'type': str}, {'name': 'url', 'verbose_name': u'url', 'type': unicode},
{'name': 'name', 'verbose_name': 'Имя', 'type': str, 'width':8000}, {'name': 'name', 'verbose_name': u'Имя', 'type': unicode},
{'name': 'data_begin', 'verbose_name': 'Дата начала', 'type': str}, {'name': 'type', 'verbose_name': u'Тип', 'type': get_place_type, 'width':8000},
{'name': 'data_end', 'verbose_name': 'Дата окончания', 'type': str}, {'name': 'data_begin', 'verbose_name': u'Дата начала', 'type': unicode},
{'name': 'audience', 'verbose_name': 'Аудитория', 'type': get_audience}, {'name': 'data_end', 'verbose_name': u'Дата окончания', 'type': unicode},
{'name': 'main_title', 'verbose_name': 'Краткое описание', 'type': str}, {'name': 'audience', 'verbose_name': u'Аудитория', 'type': get_audience},
{'name': 'description', 'verbose_name': 'Описание', 'type': str}, {'name': 'main_title', 'verbose_name': u'Краткое описание', 'type': unicode},
{'name': 'country', 'verbose_name': 'Страна', 'type': str}, {'name': 'description', 'verbose_name': u'Описание', 'type': unicode},
{'name': 'city', 'verbose_name': 'Город', 'type': str}, {'name': 'country', 'verbose_name': u'Страна', 'type': unicode},
{'name': 'theme', 'verbose_name': 'Тематика', 'type': get_theme, 'width':8000}, {'name': 'city', 'verbose_name': u'Город', 'type': unicode},
{'name': 'tag', 'verbose_name': 'Теги', 'type': get_tag, 'width':8000}, {'name': 'theme', 'verbose_name': u'Тематика', 'type': get_theme, 'width':8000},
{'name': 'tag', 'verbose_name': u'Теги', 'type': get_tag, 'width':8000},
{'name': 'address', 'verbose_name': u'Адрес', 'type': unicode},
#{'name': 'periodic', 'verbose_name': 'Периодичность', 'type': str}, #{'name': 'periodic', 'verbose_name': 'Периодичность', 'type': str},
{'name': 'web_page', 'verbose_name': 'Веб страница', 'type': str}, {'name': 'web_page', 'verbose_name': u'Веб страница', 'type': unicode},
{'name': 'time', 'verbose_name': 'Время проведения', 'type': str}, {'name': 'email', 'verbose_name': u'Email', 'type': unicode},
{'name': 'products', 'verbose_name': 'Экспонируемые продукты', 'type': str}, {'name': 'phone', 'verbose_name': u'Телефон', 'type': get_int},
{'name': 'foundation_year', 'verbose_name': 'Год основания', 'type': get_int}, {'name': 'time', 'verbose_name': u'Время проведения', 'type': unicode},
{'name': 'tax', 'verbose_name': 'Налог включен', 'type': get_bool, 'width':1000}, {'name': 'products', 'verbose_name': u'Экспонируемые продукты', 'type': unicode},
{'name': 'currency', 'verbose_name': 'Валюта', 'type': str}, {'name': 'foundation', 'verbose_name': u'Год основания', 'type': get_int},
{'name': 'max_price', 'verbose_name': 'Максимальная цена', 'type': get_int}, {'name': 'events_number', 'verbose_name': u'Год основания', 'type': get_int},
{'name': 'min_price', 'verbose_name': 'Минимальная цена', 'type': get_int}, {'name': 'staff_number', 'verbose_name': u'Год основания', 'type': get_int},
{'name': 'registration_payment', 'verbose_name': 'Регистрационный взнос', 'type': get_int}, {'name': 'specialization', 'verbose_name': u'Год основания', 'type': unicode},
{'name': 'min_closed_area', 'verbose_name': 'Минимальная цена закрытой НЕ оборудованной площади', 'type': get_int}, {'name': 'foundation_year', 'verbose_name': u'Год основания', 'type': get_int},
{'name': 'max_closed_area', 'verbose_name': 'Максимальная цена закрытой НЕ оборудованной площади', 'type': get_int}, {'name': 'tax', 'verbose_name': u'Налог включен', 'type': get_bool, 'width':1000},
{'name': 'min_closed_equipped_area', 'verbose_name': 'Минимальная цена закрытой оборудованной площади ', 'type': get_int}, {'name': 'currency', 'verbose_name': u'Валюта', 'type': unicode},
{'name': 'max_closed_equipped_area', 'verbose_name': 'Максимальная цена закрытой оборудованной площади', 'type': get_int}, {'name': 'max_price', 'verbose_name': u'Максимальная цена', 'type': get_int},
{'name': 'min_open_area', 'verbose_name': 'Минимальная цена закрытой площади', 'type': get_int}, {'name': 'min_price', 'verbose_name': u'Минимальная цена', 'type': get_int},
{'name': 'max_open_area', 'verbose_name': 'Максимальная цена открытой площади', 'type': get_int}, {'name': 'registration_payment', 'verbose_name': u'Регистрационный взнос', 'type': get_int},
{'name': 'min_area', 'verbose_name': 'Минимальная площадь', 'type': get_int}, {'name': 'min_closed_area', 'verbose_name': u'Минимальная цена закрытой НЕ оборудованной площади', 'type': get_int},
{'name': 'max_area', 'verbose_name': 'Максимальная площадь', 'type': get_int}, {'name': 'max_closed_area', 'verbose_name': u'Максимальная цена закрытой НЕ оборудованной площади', 'type': get_int},
{'name': 'is_published', 'verbose_name': 'Опубликована', 'type': get_bool}, {'name': 'min_closed_equipped_area', 'verbose_name': u'Минимальная цена закрытой оборудованной площади ', 'type': get_int},
{'name': 'canceled_by_administrator', 'verbose_name': 'Отменена администратором', 'type': get_bool} {'name': 'max_closed_equipped_area', 'verbose_name': u'Максимальная цена закрытой оборудованной площади', 'type': get_int},
{'name': 'min_open_area', 'verbose_name': u'Минимальная цена закрытой площади', 'type': get_int},
{'name': 'max_open_area', 'verbose_name': u'Максимальная цена открытой площади', 'type': get_int},
{'name': 'min_area', 'verbose_name': u'Минимальная площадь', 'type': get_int},
{'name': 'max_area', 'verbose_name': u'Максимальная площадь', 'type': get_int},
{'name': 'is_published', 'verbose_name': u'Опубликована', 'type': get_bool},
{'name': 'canceled_by_administrator', 'verbose_name': u'Отменена администратором', 'type': get_bool}
] ]
@ -122,85 +137,102 @@ def to_city(value, lang, country):
return city return city
def to_audience(value): from exposition.models import Exposition
try: def to_audience(value, model=Exposition):
if value == 'Специалисты': if value:
return 'experts' l = value.split(', ')
elif value == 'Специалисты и потребители': if l:
return 'experts and consumers' new_list = []
elif value == 'Широкая публика': for value in l:
return 'general public' for item1, item2 in BIT_AUDIENCE:
else: if value == item2:
return 'None' new_list.append(item1)
except: if new_list:
return 'None'
return reduce(lambda x,y: x|y, (getattr(model.audience, item) for item in new_list))
return 0
def to_theme(value, lang='ru'): def to_theme(value):
theme_names = value.split(', ') if isinstance(value, float):
if (value - int(value) > 0):
value = str(value)
else:
value = str(int(value))
theme_ids = value.split('.')
else:
theme_ids = value.split(',')
theme_objects = [] theme_objects = []
for name in theme_names: for id in theme_ids:
try: try:
objects = get_translation_aware_manager(Theme) theme = Theme.objects.language().get(id=int(id))
theme = objects.filter(name=name)[0] theme_objects.append(theme)
except: except Theme.DoesNotExist, ValueError:
theme = Theme() pass
theme.translate(lang)
theme.name = name
theme.save()
theme_objects.append(theme)
return theme_objects return theme_objects
def to_tag(value, lang, themes): def to_tag(value, lang, themes):
if value == [""]:
return None
value = value.replace('[', '') value = value.replace('[', '')
themes = themes.all() themes = themes.all()
# list tags by themes # list tags by themes
value = value.split(']') value = value.split(']')
arr = [] arr = []
bla = value[0].split(', ')
for theme_number, theme in enumerate(themes): for theme_number, theme in enumerate(themes):
for val in value[theme_number].split(', '): for val in value[theme_number].split(','):
if val: if val:
try: try:
objects = get_translation_aware_manager(Tag) tag = Tag.objects.language(lang).get(id=int(val), theme=theme)
tag = objects.language(lang).filter(name=val, theme=theme) arr.append(tag)
tag = tag[0] except Tag.DoesNotExist, ValueError:
except: pass
tag = Tag()
tag.theme = theme
tag.translate(lang)
tag.name = val
tag.save()
arr.append(tag)
return arr return arr
def to_theme_type(st):
if not st:
return 15
types = st.split(',')
flag = 0
flag = reduce(lambda x,y: x|y, (getattr(Theme.types, item) for item in types))
return flag
import time, xlrd
def to_date(value):
if isinstance(value, unicode):
t = time.strptime(value, "%d.%m.%Y")
if isinstance(value, float):
t = xlrd.xldate_as_tuple(value, 0)+(0,0,0)
return time.strftime("%Y-%m-%d", t)
import_settings={ import_settings={
'name': {'func': str, }, 'name': {'func': unicode, },
'url': {'func': str}, 'url': {'func': unicode},
'data_begin': {'func': str}, 'data_begin': {'func': to_date},
'data_end': {'func': str}, 'data_end': {'func': to_date},
'main_title': {'func': str}, 'main_title': {'func': unicode},
'description': {'func': str}, 'description': {'func': unicode},
'audience': {'func': to_audience}, 'audience': {'func': to_audience},
'country': {'func': to_country}, 'country': {'func': to_country},
'city': {'func': to_city, 'extra_values': 'country'}, 'city': {'func': to_city, 'extra_values': 'country'},
'theme': {'func': to_theme}, 'theme': {'func': to_theme},
'tag': {'func': to_tag, 'extra_values': 'theme'}, 'tag': {'func': to_tag, 'extra_values': 'theme'},
'periodic': {'func': str}, 'periodic': {'func': unicode},
'web_page': {'func': str}, 'web_page': {'func': unicode},
'time': {'func': str}, 'time': {'func': unicode},
'products': {'func': str}, 'products': {'func': unicode},
'foundation_year': {'func': to_int}, 'foundation_year': {'func': to_int},
'tax': {'func': bool}, 'tax': {'func': bool},
'currency': {'func': str}, 'currency': {'func': unicode},
'max_price': {'func': to_int}, 'max_price': {'func': to_int},
'min_price': {'func': to_int}, 'min_price': {'func': to_int},
'registration_payment': {'func': to_int}, 'registration_payment': {'func': to_int},
@ -213,5 +245,6 @@ import_settings={
'min_area': {'func': to_int}, 'min_area': {'func': to_int},
'max_area': {'func': to_int}, 'max_area': {'func': to_int},
'is_published': {'func': bool}, 'is_published': {'func': bool},
'canceled_by_administrator': {'func': bool} 'canceled_by_administrator': {'func': bool},
} 'types': {'func': to_theme_type}
}

@ -1,82 +1,123 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from theme.models import Theme from theme.models import Theme, Tag
from country.models import Country from country.models import Country
from organiser.models import Organiser
from accounts.models import User
from company.models import Company
from place_exposition.models import PlaceExposition
from place_conference.models import PlaceConference
from django.db.models.loading import get_model from django.db.models.loading import get_model
import xlrd, xlwt import xlwt
from excel_settings import import_settings, field_settings from excel_settings import import_settings, field_settings
languages = [code for code in settings.LANGUAGES] languages = [code for code in settings.LANGUAGES]
class ExportForm(forms.Form):
def __init__(self, *args, **kwargs):
super(ExportForm, self).__init__(*args, **kwargs)
self.workbook = xlwt.Workbook(encoding = 'utf8')
self.worksheet = self.workbook.add_sheet('My Worksheet')
class ImportEventForm(forms.Form): self.font = xlwt.Font()
excel_file = forms.FileField(label='Выберите файл') self.font.name = 'Times New Roman'
event = forms.ChoiceField(label='Выберите тип события', choices=[('exposition.Exposition', 'Выставка'), self.font.bold = True
('conference.Conference', 'Конференция'),
('seminar.Seminar', 'Семинар'), self.style = xlwt.XFStyle()
('webinar.Webinar', 'Вебинар')]) # Create the Style
self.style.font = self.font
model = None
language = forms.ChoiceField(label='Выберите язык', choices=languages) language = forms.ChoiceField(label='Выберите язык', choices=languages)
def save_events(self): def get_objects(self, data):
""" return self.model.objects.language(data['language']).all()
save events from excel file
in language from form
""" def get_fname(self):
return 'export list.xls'
def export(self):
data = self.cleaned_data data = self.cleaned_data
lang = data['language'] objects = self.get_objects(data)
f = data['excel_file'] if not objects:
book = xlrd.open_workbook(file_contents=f.read()) # not found any objects
sheet = book.sheet_by_index(0) return None
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) for row, object in enumerate(objects):
field_names = [name for name in row_list[1]] # column number
# model
model = get_model(data['event'].split('.')[0], data['event'].split('.')[1]) col = 0
for field in field_settings:
try:
value = getattr(object, field['name'])
except AttributeError:
# doesnt have such field. exit from iteration
continue
for row_number, row in enumerate(row_list): if row == 0:
# go through all rows in file # first iteration. set names. set columns width
if row_number > 1: self.worksheet.write(0, col, field.get('verbose_name', 'default'), self.style)
# first two fields are verbose name and name self.worksheet.write(1, col, field.get('name'), self.style)
if row[0] != '': self.worksheet.col(col).width = field.get('width', 3333)
# in first column ids if field['name']=='tag':
object = model.objects.language(lang).get(id=row[0]) self.worksheet.write(row+2, col, field.get('type')(value, object.theme))
else: else:
# if id blank - its a new event self.worksheet.write(row+2, col, field.get('type')(value))
object = model() col += 1
object.translate(lang) return self.workbook
for col_number, cell in enumerate(row):
# go through row cells
# field name current cell class ExportOrganiserForm(ExportForm):
field_name = field_names[col_number] model = Organiser
setting = import_settings.get(field_name)
if setting is not None: def get_fname(self):
# if setting exist for this field return 'organisers.xls'
func = setting.get('func')
if func is not None: class ExportUserForm(ExportForm):
extra_value = setting.get('extra_values') model = User
if extra_value is not None:
# if setting has extra value then def get_objects(self, data):
# it is some field like city, theme, tag return self.model.objects.all()
# that has relation and can be created
def get_fname(self):
# in function we add language(need for relation fields) return 'users.xls'
# and extra value from object (like for city need country)
# условие заглушка для мени ту мени class ExportThemeForm(ExportForm):
if object.id == None and (field_name=='theme' or field_name=='tag'): model = Theme
pass
else: def get_fname(self):
value = func(cell, lang, getattr(object, extra_value)) return 'themes.xls'
else:
value = func(cell) class ExportTagForm(ExportForm):
# условие заглушка для мени ту мени model = Tag
if object.id == None and (field_name=='theme' or field_name=='tag'):
pass def get_fname(self):
else: return 'tags.xls'
setattr(object, field_name, value)
class ExportPlaceExpositionForm(ExportForm):
object.save() model = PlaceExposition
def get_fname(self):
return 'places.xls'
class ExportPlaceConferenceForm(ExportForm):
model = PlaceConference
def get_fname(self):
return 'places.xls'
class ExportCompanyForm(ExportForm):
model = Company
def get_fname(self):
return 'companies.xls'
class ExportEventForm(forms.Form): class ExportEventForm(forms.Form):
@ -90,7 +131,7 @@ class ExportEventForm(forms.Form):
theme = forms.ModelMultipleChoiceField(label='Направление', queryset=Theme.objects.all(), required=False) theme = forms.ModelMultipleChoiceField(label='Направление', queryset=Theme.objects.all(), required=False)
country = forms.ModelMultipleChoiceField(label='Страны', queryset=Country.objects.all(), required=False) country = forms.ModelMultipleChoiceField(label='Страны', queryset=Country.objects.all(), required=False)
def export_events(self): def export(self):
data = self.cleaned_data data = self.cleaned_data
# get model # get model
model = get_model(data['event'].split('.')[0], data['event'].split('.')[1]) model = get_model(data['event'].split('.')[0], data['event'].split('.')[1])
@ -119,6 +160,7 @@ class ExportEventForm(forms.Form):
for row, object in enumerate(objects): for row, object in enumerate(objects):
# column number # column number
col = 0 col = 0
for field in field_settings: for field in field_settings:
try: try:

@ -0,0 +1,237 @@
# -*- coding: utf-8 -*-
from django import forms
from django.conf import settings
from theme.models import Theme, Tag
from place_exposition.models import PlaceExposition
from place_conference.models import PlaceConference
from country.models import Country
from organiser.models import Organiser
from django.db.models.loading import get_model
import xlrd, xlwt
from excel_settings import import_settings
languages = [code for code in settings.LANGUAGES]
class ImportForm(forms.Form):
"""
abstract form for importing models from excel file to database
"""
model = None
excel_file = forms.FileField(label='Выберите файл')
language = forms.ChoiceField(label='Выберите язык', choices=languages)
def save_file(self):
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]]
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
try:
object = self.model.objects.language(lang).get(id=int(row[0]))
except ValueError:
object = self.model()
object.translate(lang)
except self.model.DoesNotExist:
object = self.model(id= int(row[0]))
object.translate(lang)
else:
# if id blank - its a new event
object = self.model()
object.translate(lang)
for col_number, cell in enumerate(row):
# go through row cells
# field name current cell
field_name = field_names[col_number]
if field_name =='theme':
# need save object before saving manytomany field
object.save()
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 ImportOrganiserForm(ImportForm):
model = Organiser
class ImportThemeForm(ImportForm):
model = Theme
class ImportPlaceExpositionForm(ImportForm):
model = PlaceExposition
class ImportPlaceConferenceForm(ImportForm):
model = PlaceConference
class ImportEventForm(ImportForm):
"""
extended form for importing one type of event
"""
event = forms.ChoiceField(label='Выберите тип события', choices=[('exposition.Exposition', 'Выставка'),
('conference.Conference', 'Конференция'),
('seminar.Seminar', 'Семинар'),
('webinar.Webinar', 'Вебинар')])
def save_file(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
try:
object = self.model.objects.language(lang).get(id=int(row[0]))
except ValueError:
object = self.model()
object.translate(lang)
except self.model.DoesNotExist:
object = self.model(id= int(row[0]))
object.translate(lang)
else:
# if id blank - its a new event
object = model()
object.translate(lang)
for col_number, cell in enumerate(row):
# go through row cells
# field name current cell
field_name = field_names[col_number]
if field_name =='theme':
# need save object before saving manytomany field
object.save()
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)
if cell:
value = func(cell, lang, getattr(object, extra_value))
else:
value = None
else:
value = func(cell)
if value:
setattr(object, field_name, value)
object.save()
class ImportTagForm(ImportForm):
"""
hacked problem with importing theme field in save_file method
"""
model = Tag
def save_file(self):
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]]
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
try:
object = self.model.objects.language(lang).get(id=int(row[0]))
except ValueError:
object = self.model()
object.translate(lang)
except self.model.DoesNotExist:
object = self.model(id= int(row[0]))
object.translate(lang)
else:
# if id blank - its a new event
object = self.model()
object.translate(lang)
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)
if field_name != 'theme':
setattr(object, field_name, value)
else:
setattr(object, field_name, value[0])
object.save()

@ -1,64 +0,0 @@
# -*- 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
from django.db.models.loading import get_model
#
import xlwt
import xlrd
#
from custom_forms import ImportEventForm, ExportEventForm
from excel_settings import field_settings, import_settings
relation_fields = ['city']
@login_required
def import_event(request):
args = {}
form = ImportEventForm()
args.update(csrf(request))
args['form'] = form
if request.POST:
form = ImportEventForm(request.POST, request.FILES)
if form.is_valid():
form.save_events()
args['message'] = 'Success'
return render_to_response('import_event.html', args)
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
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:
f_name = form.get_fname()
return xls_to_response(workbook, f_name)
#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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save