Merged branches

remotes/origin/1203
Назар Котюк 11 years ago
commit 0a97d52be9
  1. 2
      .gitignore
  2. 26
      accounts/edit_forms.py
  3. 20
      accounts/forms.py
  4. 117
      accounts/models.py
  5. 1
      accounts/urls.py
  6. 10
      accounts/user_catalog_urls.py
  7. 101
      accounts/views.py
  8. 9
      article/admin.py
  9. 46
      article/forms.py
  10. 139
      article/models.py
  11. 22
      article/urls.py
  12. 165
      article/views.py
  13. 2
      city/admin.py
  14. 2
      city/forms.py
  15. 22
      city/management/commands/city_slug.py
  16. 30
      city/management/commands/city_update_from_old.py
  17. 26
      city/models.py
  18. 40
      company/edit_forms.py
  19. 82
      company/edit_views.py
  20. 2
      company/forms.py
  21. 15
      company/models.py
  22. 5
      company/search_indexes.py
  23. 50
      company/urls.py
  24. 53
      company/views.py
  25. 84
      conference/admin.py
  26. 14
      conference/admin_urls.py
  27. 100
      conference/forms.py
  28. 170
      conference/models.py
  29. 29
      conference/search_indexes.py
  30. 75
      conference/urls.py
  31. 451
      conference/views.py
  32. 12
      core/simple_index_view.py
  33. 39
      country/management/commands/country_update_from_old.py
  34. 105
      country/manager.py
  35. 78
      country/models.py
  36. 48
      exposition/admin.py
  37. 5
      exposition/admin_urls.py
  38. 69
      exposition/forms.py
  39. 201
      exposition/management/commands/expo_old.py
  40. 60
      exposition/management/commands/expo_organiser.py
  41. 77
      exposition/management/commands/expo_test.py
  42. 40
      exposition/management/commands/exposition_load.py
  43. 89
      exposition/management/commands/fix_logo.py
  44. 68
      exposition/management/commands/imp_stat.py
  45. 20
      exposition/management/commands/test.py
  46. 5
      exposition/manager.py
  47. 114
      exposition/models.py
  48. 5
      exposition/search_indexes.py
  49. 124
      exposition/urls.py
  50. 176
      exposition/views.py
  51. 4
      file/forms.py
  52. 3
      file/models.py
  53. 2
      functions/admin_forms.py
  54. 5
      functions/admin_views.py
  55. 50
      functions/cache_mixin.py
  56. 13
      functions/custom_views.py
  57. 2
      functions/form_check.py
  58. 5
      functions/model_mixin.py
  59. 114
      functions/models_methods.py
  60. 53
      functions/search_forms.py
  61. 2
      functions/signal_handlers.py
  62. 13
      functions/translate.py
  63. 15
      import_xls/admin.py
  64. 4
      import_xls/admin_urls.py
  65. 32
      import_xls/excel_settings.py
  66. 22
      import_xls/export_forms.py
  67. 48
      import_xls/utils.py
  68. 57
      meta/admin.py
  69. 11
      meta/admin_urls.py
  70. 23
      meta/decorators.py
  71. 48
      meta/forms.py
  72. 88
      meta/models.py
  73. 51
      meta/views.py
  74. 31
      organiser/management/commands/organiser_from_old_db.py
  75. 1
      organiser/models.py
  76. 114
      password_reset/templates/password_reset/recovery_email_expo.html
  77. 38
      password_reset/views.py
  78. 27
      place_exposition/admin.py
  79. 3
      place_exposition/admin_urls.py
  80. 22
      place_exposition/forms.py
  81. 8
      place_exposition/management/commands/convert_logo.py
  82. 165
      place_exposition/management/commands/place_exposition_load.py
  83. 44
      place_exposition/models.py
  84. 15
      place_exposition/urls.py
  85. 32
      place_exposition/views.py
  86. 52
      proj/admin.py
  87. 4
      proj/admin_urls.py
  88. 4
      proj/production.py
  89. 194
      proj/settings.py
  90. 141
      proj/sitemaps.py
  91. 78
      proj/urls.py
  92. 52
      proj/views.py
  93. 39
      registration/backends/default/views.py
  94. 31
      registration/forms.py
  95. 36
      registration/models.py
  96. 7
      service/forms.py
  97. 37
      service/models.py
  98. 32
      service/order_forms.py
  99. 12
      service/urls.py
  100. 55
      service/views.py
  101. Some files were not shown because too many files have changed in this diff Show More

2
.gitignore vendored

@ -11,3 +11,5 @@ Thumbs.db
npm-debug.log
/proj/local.py

@ -60,17 +60,22 @@ class HomeForm(forms.ModelForm):
class WorkForm(forms.ModelForm):
position = forms.CharField(label=_(u'Укажите вашу должность'),
required=False, widget=forms.TextInput())
company = forms.CharField(label=_(u'Укажите вашу компанию'), required=False,
widget=forms.HiddenInput(attrs={'class': 'select2'}))
company = forms.CharField(label=_(u'Место работы'), widget=forms.HiddenInput(attrs={'class': 'select2'}))
def __init__(self, *args, **kwargs):
super(WorkForm, self).__init__(*args, **kwargs)
if self.instance.company:
self.fields['company'].widget = forms.HiddenInput(attrs={'class': 'select2', 'data-init-text': self.instance.company.name})
class Meta:
model = User
fields = ('position', 'company')
def clean_company(self):
if not self.cleaned_data.get('company'):
return None
try:
return Company.objects.get(id=self.cleaned_data['company'])
except Company.DoesNotExist:
@ -87,9 +92,26 @@ class AboutCompanyForm(forms.ModelForm):
class PhoneForm(forms.ModelForm):
phone = forms.CharField(label=_(u'Контактный телефон'), required=False)
show_phone = forms.BooleanField(label=_(u'Контактный телефон'), required=False)
class Meta:
model = Profile
fields = ('phone',)
fields = ('phone', 'show_phone')
def clean_phone(self):
phone = self.cleaned_data['phone']
if not phone:
return
deduct = ('-','(',')','.',' ', '+')
for elem in deduct:
phone = phone.replace(elem, '')
if phone.isdigit():
return phone
else:
raise forms.ValidationError(_(u'Введите правильный телефон'))
class EmailForm(forms.ModelForm):
email = forms.EmailField(label=_(u'Ваш e-mail'), required=False)

@ -218,10 +218,10 @@ class EmailAnnouncementForm(forms.Form):
class RegistrationCompleteForm(forms.ModelForm):
country = forms.ChoiceField(label='Страна', choices=[(c.id, c.name) for c in Country.objects.all()],
country = forms.ModelChoiceField(label='Страна', queryset= Country.objects.all(),
widget=forms.Select(attrs={'class': 'select2'}))
city = forms.CharField(label='Город', widget=forms.HiddenInput())
url = forms.CharField(widget=forms.TextInput(attrs={'placeholder': _(u'адрес страны(обязательно)')}))
url = forms.CharField(widget=forms.TextInput(attrs={'placeholder': _(u'url(обязательно)')}))
code_country = forms.ChoiceField(label=_(u'код страны'), initial='70',
choices=[(str(c.phone_code), '+'+str(c.phone_code)) for c in Country.objects.all() if c.phone_code is not None],
@ -254,12 +254,6 @@ class RegistrationCompleteForm(forms.ModelForm):
return None
def clean_country(self):
try:
return Country.objects.get(id=self.cleaned_data['country'])
except City.DoesNotExist:
return None
def clean_url(self):
url = self.cleaned_data['url']
if not is_latin(url):
@ -317,18 +311,14 @@ class FeedFilterForm(forms.Form):
th = forms.MultipleChoiceField(label=_(u'Тематика'), choices=[(item.id, item.name) for item in Theme.active.all()],
required=False, widget=forms.CheckboxSelectMultiple())
tg = forms.CharField(label=_(u'Теги'), required=False, widget=forms.CheckboxSelectMultiple())
area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in Area.objects.all_sorted()],
area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in Area.objects.language().all()],
required=False, widget=forms.CheckboxSelectMultiple())
co = forms.MultipleChoiceField(label=_(u'Страна'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in Country.objects.select_related('exposition_country')\
.filter(exposition_country__country__isnull=False, translations__language_code=translation.get_language())\
.order_by('translations__name').distinct()]
choices=[(item.id, item.name) for item in Country.objects.expo_countries()]
)
ci = forms.MultipleChoiceField(label=_(u'Город'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in City.objects.select_related('exposition_city')\
.filter(exposition_city__city__isnull=False, translations__language_code=translation.get_language())\
.order_by('translations__name').distinct()]
choices=[(item.id, item.name) for item in City.used.expo_cities()]
)
fr = forms.DateField(required=False,

@ -132,8 +132,7 @@ class User(AbstractBaseUser, PermissionsMixin):
translator = models.ForeignKey('translator.Translator', verbose_name='Переводчик', blank=True, null=True,
unique=True,
on_delete=models.PROTECT, related_name='user')
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, related_name='users')
position = models.CharField(verbose_name='Должность', max_length=255, blank=True)
objects = UserManager()
@ -223,6 +222,23 @@ class User(AbstractBaseUser, PermissionsMixin):
"""
return self.seminar_users.language().select_related('country', 'city').all()
def remove_from_calendar(self, data):
expo = data['expo']
conf = data['conf']
seminar = data['seminar']
webinar = data['webinar']
calendar = self.calendar
if expo:
calendar.expositions.remove(*expo)
if conf:
calendar.conferences.remove(*conf)
if seminar:
calendar.seminars.remove(*seminar)
if webinar:
calendar.webinars.remove(*webinar)
class Profile(models.Model):
@ -237,15 +253,16 @@ class Profile(models.Model):
on_delete=models.PROTECT)
about_company = models.TextField(verbose_name=_(u'Описание компании'), blank=True)
phone = models.BigIntegerField(verbose_name='Телефон', blank=True, null=True)
phone = models.BigIntegerField(verbose_name=_(u'Телефон'), blank=True, null=True)
show_phone = models.NullBooleanField(verbose_name=_(u'Показывать телефон'), blank=True, null=True, default=1)
web_page = models.URLField(verbose_name='Вебсайт',blank=True)
about = models.TextField(verbose_name='О себе', blank=True)
avatar = models.ImageField(verbose_name='Фото', upload_to='accounts/avatar/', blank=True)
skype = models.CharField(blank=True, max_length=255)
facebook = models.URLField(verbose_name=_(u'Facebook'), blank=True)
twitter = models.URLField(verbose_name=_(u'Twitter'), blank=True)
linkedin = models.URLField(verbose_name=_(u'LinkedIn'), blank=True)
vk = models.URLField(verbose_name=_(u'В контакте'), blank=True)
facebook = models.URLField(verbose_name=_(u'Facebook'), blank=True, max_length=255)
twitter = models.URLField(verbose_name=_(u'Twitter'), blank=True,max_length=255)
linkedin = models.URLField(verbose_name=_(u'LinkedIn'), blank=True, max_length=255)
vk = models.URLField(verbose_name=_(u'В контакте'), blank=True, max_length=255)
# meta
title = models.CharField(max_length=255, blank=True)
@ -385,86 +402,10 @@ def create_user_inf(sender, instance, created, **kwargs):
calculate_rating(instance)
post_save.connect(create_user_inf, sender=User)
#need import after User Model, because User imported in "organiser.models"
#from organiser.models import Organiser
'''
def create_profiles(sender, **kw):
"""
create Translator profile if "is_translator" field in User model true
if it's false delete Translator profile connected to User
create Organiser profile if "is_organiser" field in User model true
if it's false delete Organiser profile connected to User
"""
user = kw["instance"]
if user.is_translator and not user.translator.all():
#check flag is_translator and if translator profile already exist
translator = TranslatorProfile(user=user)
translator.save()
if not user.is_translator:
TranslatorProfile.objects.filter(user = user).delete()
if user.is_organiser and not user.organiser.all():
#check flag is_organiser and if organiser profile already exist
organiser = Organiser(user=user)
if user.country:
organiser.country = user.country
if user.city:
organiser.city = user.city
organiser.save()
data = {'name_ru':user.get_full_name()}
zero_fields = {}
fill_trans_fields_all(Organiser, organiser, data, None, zero_fields)
#populate empty fields and fields which was already populated
organiser_id = getattr(organiser, 'id')
populate_all(Organiser, data, organiser_id, zero_fields)
if not user.is_organiser:
Organiser.objects.filter(user = user).delete()
post_save.connect(create_profiles, sender=User)
'''
"""
class MyUserAuthBackend(object):
def check_md5_password(self, db_password, supplied_password):
return md5(supplied_password).hex_digest(), db_password
def authenticate(self, username=None, password=None, **kwargs):
# Authenticate a user based on email address as the user name.
UserModel = get_user_model()
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
try:
user = UserModel._default_manager.get_by_natural_key(username)
if check_password(password, user.password):
# user.set_password(password)
# user.save()
return user
#if user.check_password(password):
# return user
except UserModel.DoesNotExist:
return None
def post_profile(sender, instance, created, **kwargs):
user = instance.user
calculate_rating(user)
post_save.connect(create_user_inf, sender=User)
post_save.connect(post_profile, sender=Profile)
def get_user(self, user_id):
try:
UserModel = get_user_model()
return UserModel._default_manager.get(pk=user_id)
except UserModel.DoesNotExist:
return None
"""

@ -15,6 +15,7 @@ urlpatterns = patterns('',
url(r'^profile/$', login_required(ProfileView.as_view())),
url(r'^profile/company/$', login_required(ProfileCompanyView.as_view())),
url(r'^profile/settings/$', login_required(SettingsView.as_view())),
url(r'^profile/calendar/remove/$', 'accounts.views.remove_from_calendar'),
url(r'^profile/calendar/$', login_required(CalendarView.as_view())),
url(r'^profile/feed/page/(?P<page>\d+)/$', Feed.as_view()),
url(r'^profile/feed/$', login_required(Feed.as_view())),

@ -3,14 +3,14 @@ from django.contrib.auth.decorators import login_required
from views import SettingsView, ProfileView, CalendarView, UserView, UserExpositionsView, UserConferenceView, UserSeminarView
urlpatterns = patterns('',
url(r'^(?P<url>.*)/expositions/(?P<page>\d+)/$', UserExpositionsView.as_view()),
url(r'^(?P<url>.*)/expositions/$', UserExpositionsView.as_view()),
url(r'^(?P<url>.*)/expositions/(?P<page>\d+)/$', UserExpositionsView.as_view(), {'meta_id': 72}),
url(r'^(?P<url>.*)/expositions/$', UserExpositionsView.as_view(), {'meta_id': 72}),
url(r'^(?P<url>.*)/seminars/(?P<page>\d+)/$', UserSeminarView.as_view()),
url(r'^(?P<url>.*)/seminars/$', UserSeminarView.as_view()),
url(r'^(?P<url>.*)/conferences/(?P<page>\d+)/$', UserConferenceView.as_view()),
url(r'^(?P<url>.*)/conferences/$', UserConferenceView.as_view()),
url(r'^(?P<url>.*)/conferences/(?P<page>\d+)/$', UserConferenceView.as_view(), {'meta_id': 73}),
url(r'^(?P<url>.*)/conferences/$', UserConferenceView.as_view(), {'meta_id': 73}),
url(r'^(?P<url>.*)/events/(?P<page>\d+)/$', UserView.as_view()),
url(r'^(?P<url>.*)/events/$', UserView.as_view()),
url(r'^(?P<url>.*)/$', UserView.as_view()),
url(r'^(?P<url>.*)/$', UserView.as_view(), {'meta_id': 71}),
)

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import dateutil.relativedelta as rdelta
import json, datetime
import calendar as python_calendar
from django.shortcuts import get_object_or_404
@ -55,7 +56,7 @@ class CalendarView(TemplateView):
"""
context = super(CalendarView, self).get_context_data(**kwargs)
now = timezone.now().replace(microsecond=0, second=0, minute=0, hour=0)
now = datetime.datetime.now().replace(microsecond=0, second=0, minute=0, hour=0)
context['current_day'] = now
year = self.request.GET.get('year')
@ -69,8 +70,8 @@ class CalendarView(TemplateView):
# events in current months
number_of_days = python_calendar.monthrange(now.year, now.month)[1]
# number of days in current month
days = [timezone.make_aware(datetime.datetime(now.year, now.month, i+1), timezone.get_default_timezone()) for i in range(number_of_days)]
context['days'] = days
days = [datetime.datetime(now.year, now.month, i+1) for i in range(number_of_days)]
#context['days'] = days
calendar = self.request.user.calendar
# events in current month
@ -78,17 +79,33 @@ class CalendarView(TemplateView):
else:
number_of_days = python_calendar.monthrange(year, month)[1]
days = [timezone.make_aware(datetime.datetime(year, month, i+1), timezone.get_default_timezone()) for i in range(number_of_days)]
days = [datetime.datetime(year, month, i+1) for i in range(number_of_days)]
# number of days in current month
context['days'] = days
#context['days'] = days
calendar = self.request.user.calendar
now = now.replace(year=year, month=month, day=1)
# events in current month
context['events'] = calendar.events_by_month(now)
# add days from previous mondey to next sunday
first_day = days[0]
if first_day.weekday() != 0:
past_monday = first_day + rdelta.relativedelta(days=-1, weekday=rdelta.MO(-1))
a = [past_monday + datetime.timedelta(days=x) for x in range((first_day - past_monday).days)]
days = a + days
last_day = days[-1]
if last_day != 6:
next_sunday = last_day + rdelta.relativedelta(days=1, weekday=rdelta.SU(+1))
b = [last_day + datetime.timedelta(days=x+1) for x in range((next_sunday - last_day).days)]
days += b
events = context['events']
days = context['days']
context['days'] = days
#days = context['days']
event_in_day = False
counter = 0
dates_with_events = []
@ -190,21 +207,27 @@ class ProfileCompanyView(TemplateView):
class UserView(TemplateView):
from meta.views import MetadataMixin
class UserView(MetadataMixin, TemplateView):
"""
display user information for another users
"""
template_name = 'accounts/user.html'
template_name = 'client/accounts/user.html'
def get_context_data(self, **kwargs):
context = super(UserView, self).get_context_data(**kwargs)
def get_user(self):
url = self.kwargs.get('url')
try:
url = int(url)
user = get_object_or_404(User, id=url)
except ValueError:
user = get_object_or_404(User, url=url)
self.kwargs['user_full_name'] = user.get_full_name()
return user
def get_context_data(self, **kwargs):
user = self.get_user()
context = super(UserView, self).get_context_data(**kwargs)
if user == self.request.user:
profile = user.profile
@ -213,11 +236,9 @@ class UserView(TemplateView):
'home_form': HomeForm(instance=profile), 'work_form': WorkForm(instance=user),
'about_company_form': AboutCompanyForm(instance=profile), 'phone_form': PhoneForm(instance=profile),
'email_form': EmailForm(instance=user), 'web_page_form': WebPageForm(instance=profile),
'social_form': SocialForm(instance=profile), 'about_form': AboutForm(instance=profile)
'social_form': SocialForm(instance=profile), 'about_form': AboutForm(instance=profile),
'company_form': CreateCompanyForm()
}
if not user.company:
company_form = {'company_form': CreateCompanyForm()}
context.update(company_form)
context.update(profile_forms)
@ -246,8 +267,8 @@ class BaseProfileView(ProfileInvalidView):
def form_valid(self, form):
profile = self.request.user.profile
form = self.form_class(self.request.POST, instance=profile)
form.save()
response = {'success': True}
profile = form.save()
response = {'success': True, 'rating': profile.user.rating}
return HttpResponse(json.dumps(response), content_type='application/json')
class WorkView(ProfileInvalidView):
@ -260,10 +281,10 @@ class WorkView(ProfileInvalidView):
user = self.request.user
form = self.form_class(self.request.POST, instance=user)
user = form.save()
company = user.company
#company = user.company
response = {'success': True, 'url':company.get_permanent_url()}
#response = {'success': True, 'url':company.get_permanent_url()}
response = {'success': True, 'rating': user.rating}
return HttpResponse(json.dumps(response), content_type='application/json')
@ -278,10 +299,10 @@ class AvatarView(BaseProfileView):
def form_valid(self, form):
profile = self.request.user.profile
form = self.form_class(self.request.POST, self.request.FILES, instance=profile)
form.save()
profile = form.save()
if self.request.is_ajax():
im = get_thumbnail(profile.avatar, '100x100', crop='center')
response = {'success': True, 'url': im.url}
im = get_thumbnail(profile.avatar, '100x100', format="PNG")
response = {'success': True, 'url': im.url, 'rating': profile.user.rating}
return HttpResponse(json.dumps(response), content_type='application/json')
else:
return HttpResponseRedirect('/profile/')
@ -337,8 +358,8 @@ class NameView(ProfileInvalidView):
def form_valid(self, form):
user = self.request.user
form = self.form_class(self.request.POST, instance=user)
form.save()
response = {'success': True}
user = form.save()
response = {'success': True, 'rating': user.rating}
return HttpResponse(json.dumps(response), content_type='application/json')
@ -373,7 +394,7 @@ class UserEventView(ListView):
context['event_type'] = self.event_type
return context
class UserExpositionsView(UserEventView):
class UserExpositionsView(MetadataMixin, UserEventView):
"""
return template with list of expos that user joined
"""
@ -383,10 +404,11 @@ class UserExpositionsView(UserEventView):
url = self.kwargs.get('url')
user = get_user(url)
self.obj = user
self.kwargs['user_full_name'] = user.get_full_name()
return user.get_expos()
class UserConferenceView(UserEventView):
class UserConferenceView(MetadataMixin, UserEventView):
"""
return template with list of confs that user joined
"""
@ -396,6 +418,7 @@ class UserConferenceView(UserEventView):
url = self.kwargs.get('url')
user = get_user(url)
self.obj = user
self.kwargs['user_full_name'] = user.get_full_name()
return user.get_confs()
class UserSeminarView(UserEventView):
@ -441,7 +464,7 @@ def change_password(request):
from django.views.generic.edit import FormMixin
class Feed(ListView):
template_name = 'client/accounts/feed.html'
paginate_by = 5
paginate_by = 10
model = Exposition
filter_form = FeedFilterForm
success_url = '/profile/feed/'
@ -465,4 +488,24 @@ class Feed(ListView):
user = self.request.user
filter_form = self.filter_form(user=user)
context['filter_form'] = filter_form
return context
return context
@login_required
def remove_from_calendar(request):
if request.GET:
expo = request.GET.get('expo')
conf = request.GET.get('conf')
seminar = request.GET.get('seminar')
webinar = request.GET.get('webinar')
data = {'expo': expo if expo is None else json.loads(expo),
'conf': conf if conf is None else json.loads(conf),
'seminar': seminar if seminar is None else json.loads(seminar),
'webinar': webinar if webinar is None else json.loads(webinar)}
user = request.user
user.remove_from_calendar(data)
return HttpResponse(json.dumps({'success': True}), content_type='application/json')
else:
return Http404

@ -9,7 +9,7 @@ from django.contrib.contenttypes.models import ContentType
from forms import ArticleForm, ArticleDeleteForm, Article, NewsForm
from theme.models import Tag
from file.models import FileModel, TmpFile
from file.forms import FileModelForm
from file.forms import FileModelForm, FileForm
#custom views
from functions.custom_views import objects_list, add_object_with_file, delete_object
@ -180,7 +180,13 @@ class BlogView(FormView):
def get_context_data(self, **kwargs):
context = super(BlogView, self).get_context_data(**kwargs)
self.set_obj()
context['article'] = self.obj
if context['article']:
context['file_form'] = FileForm(initial={'model': 'article.Article'})
context['files'] = FileModel.objects.filter(content_type=ContentType.objects.get_for_model(context['article']),
object_id=getattr(context['article'], 'id'))
context['languages'] = settings.LANGUAGES
return context
@ -188,6 +194,7 @@ class BlogView(FormView):
class NewsList(ListView):
model = Article
template_name = 'article/article_admin_list.html'
paginate_by = 20
def get_queryset(self):
return self.model.objects.news()

@ -4,6 +4,7 @@ from django.conf import settings
from ckeditor.widgets import CKEditorWidget
from django.core.exceptions import ValidationError
from django.forms.util import ErrorList
from django.utils.translation import ugettext as _
#functions
from functions.translate import fill_with_signal
from functions.files import check_tmp_files
@ -226,4 +227,47 @@ class BlogForm(forms.ModelForm):
widget=forms.TextInput(attrs={'style':'width: 550px'}))
self.fields['descriptions_%s' % code] = forms.CharField(label='Кейвордс', required=False, max_length=255,
widget=forms.TextInput(attrs={'style':'width: 550px'}))
"""
"""
class ArticleFilterForm(forms.Form):
theme = forms.MultipleChoiceField(label=_(u'Тематика:'), required=False,
choices=[(item.id, item.name) for item in Theme.objects.language().all()])
tag = forms.CharField(label=_(u'Теги:'), widget=forms.HiddenInput(), required=False)
'''
def __init__(self, *args, **kwargs):
"""
create dynamical translated fields fields
"""
super(ArticleFilterForm, self).__init__(*args, **kwargs)
ids = [item['theme_id'] for item in list(Article.objects.blogs().values('theme_id').distinct())]
self.fields['theme'] = forms.MultipleChoiceField(label=_(u'Тематика:'), required=False,
choices=[(item.id, item.name) for item in Theme.objects.language().filter(id__in=ids)])
'''
class BlogFilterForm(forms.Form):
tag = forms.CharField(label=_(u'Теги:'), widget=forms.HiddenInput(), required=False)
def __init__(self, *args, **kwargs):
"""
create dynamical translated fields fields
"""
super(BlogFilterForm, self).__init__(*args, **kwargs)
ids = [item['theme'] for item in list(Article.objects.blogs().values('theme').distinct())]
self.fields['theme'] = forms.MultipleChoiceField(label=_(u'Тематика:'), required=False,
choices=[(item.id, item.name) for item in Theme.objects.language().filter(id__in=ids)])
class NewsFilterForm(forms.Form):
tag = forms.CharField(label=_(u'Теги:'), widget=forms.HiddenInput(), required=False)
def __init__(self, *args, **kwargs):
"""
create dynamical translated fields fields
"""
super(NewsFilterForm, self).__init__(*args, **kwargs)
ids = [item['theme'] for item in list(Article.objects.news().values('theme').distinct())]
self.fields['theme'] = forms.MultipleChoiceField(label=_(u'Тематика:'), required=False,
choices=[(item.id, item.name) for item in Theme.objects.language().filter(id__in=ids)])

@ -1,16 +1,22 @@
# -*- coding: utf-8 -*-
import copy
from django.db import models
from django.contrib.contenttypes import generic
from django.utils.translation import ugettext_lazy as _
from django.utils import translation
from django.utils.timezone import now
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from django.utils.html import strip_tags
from sorl.thumbnail import ImageField
from functions.url_utils import slugify, unique_slug
from functions.model_utils import base_concrete_model
from functions.form_check import translit_with_separator
from django.core.cache import cache
class ArticleManager(TranslationManager):
cache_time = 60
def safe_get(self, **kwargs):
model = self.model
try:
@ -23,14 +29,38 @@ class ArticleManager(TranslationManager):
return queryset of news
"""
model = self.model
return model.objects.filter(type=model.news)
return self.language().filter(type=model.news)
def blogs(self):
"""
return queryset of blogs
"""
model = self.model
return model.objects.filter(type=model.blog)
return self.language().filter(type=model.blog)
def main_page_news(self):
lang = translation.get_language()
key = 'main_page_news_%s'%lang
cached_news = cache.get(key)
if cached_news:
return cached_news
else:
news = list(self.news().filter(publish_date__isnull=False).order_by('-main_page', '-publish_date')[:3])
cache.set(key, news, self.cache_time)
return news
def main_page_blogs(self):
lang = translation.get_language()
key = 'main_page_blogs_%s'%lang
cached_blogs = cache.get(key)
if cached_blogs:
return cached_blogs
else:
blogs = list(self.blogs().filter(publish_date__isnull=False).order_by('-main_page', '-publish_date')[:3])
cache.set(key, blogs, self.cache_time)
return blogs
return list(self.blogs().filter(publish_date__isnull=False).order_by('-main_page', '-publish_date')[:3])
class Article(TranslatableModel):
"""
@ -73,23 +103,27 @@ class Article(TranslatableModel):
gen_description = models.BooleanField(_("Generate description"),
help_text=_("If checked, the description will be automatically "
"generated from content. Uncheck if you want to manually "
"set a custom description."), default=True)
"set a custom description."), default=False)
# published = models.
created = models.DateTimeField(auto_now_add=True)
created = models.DateTimeField()
modified = models.DateTimeField(auto_now=True)
#translated fields
translations = TranslatedFields(
main_title = models.CharField(max_length=100),
main_title = models.CharField(max_length=255),
preview = models.TextField(),
description = models.TextField(),
description = models.TextField(blank=False),
#-----meta
title = models.CharField(max_length=255, blank=True),
descriptions = models.CharField(max_length=255, blank=True),
keywords = models.CharField(max_length=255, blank=True),
)
files = generic.GenericRelation('file.FileModel', content_type_field='content_type', object_id_field='object_id')
class Meta:
ordering = ['-created']
def __unicode__(self):
return self.lazy_translation_getter('main_title', self.pk)
@ -121,8 +155,8 @@ class Article(TranslatableModel):
self.slug = self.generate_unique_slug()
#Set the description field on save.
if self.gen_description:
self.description = strip_tags(self.description_from_content())
#if self.gen_description:
# self.description = strip_tags(self.description_from_content())
super(Article, self).save(*args, **kwargs)
def description_from_content(self):
@ -140,7 +174,9 @@ class Article(TranslatableModel):
# slug lookup.
concrete_model = base_concrete_model(Article, self)
slug_qs = concrete_model.objects.exclude(id=self.id)
return unique_slug(slug_qs, "slug", self.get_slug())
slug = unique_slug(slug_qs, "slug", self.get_slug())
slug = translit_with_separator(slug)
return slug
def get_slug(self):
"""
@ -184,60 +220,6 @@ class Article(TranslatableModel):
"""
return self._get_next_or_previous_by_publish_date(False, **kwargs)
def clone(self):
"""
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
# url must be unique
duplicate.url += '_copy'
if Article.objects.safe_get(url=duplicate.url):
#already has copy this instance
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()
# but lost all ManyToMany relations and Translations.
'''
# copy relations
for field in self._meta.many_to_many:
source = getattr(self, field.attname)
destination = getattr(duplicate, field.attname)
for item in source.all():
destination.add(item)
# copy translations
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
def admin_url(self):
if self.type == 1:
@ -247,9 +229,36 @@ class Article(TranslatableModel):
def get_permanent_url(self):
if self.type == 1:
return '/blogs/%s'%self.slug
return '/blogs/%s/'%self.slug
elif self.type == 2:
return '/news/%s'%self.slug
return '/news/%s/'%self.slug
def get_blog_preview(self):
preview = self.files.filter(purpose='preview')
if preview:
return preview[0]
else:
return None
def get_blog_preview2(self):
preview = self.files.filter(purpose='preview2')
if preview:
return preview[0]
else:
return None
def get_catalog(self):
if self.type == 1:
return '/blogs/'
elif self.type == 2:
return '/news/'
def similar(self):
themes = [item ['id'] for item in self.theme.all().values('id')]
return list(Article.objects.language().exclude(id=self.id).filter(type=self.type, publish_date__isnull=False, theme__in=themes).distinct().order_by('-publish_date')[:3])
from django.db.models.signals import post_save
from functions.signal_handlers import post_save_handler

@ -1,10 +1,22 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from views import BlogList, NewsList, BlogDetail, NewsDetail
from views import BlogList, NewsList, BlogDetail, NewsDetail, NewsTagCatalog, BlogsTagCatalog
urlpatterns = patterns('',
url(r'blogs/$', BlogList.as_view()),
url(r'news/$', NewsList.as_view()),
url(r'blogs/(?P<slug>.*)$', BlogDetail.as_view()),
url(r'news/(?P<slug>.*)$', NewsDetail.as_view()),
url(r'^blogs/tag/(?P<slug>.*)/page/(?P<page>\d+)/$', BlogsTagCatalog.as_view(), {'meta_id':75}),
url(r'^blogs/page/(?P<page>\d+)/$', BlogList.as_view(), {'meta_id':79}),
url(r'^blogs/tag/(?P<slug>.*)/$', BlogsTagCatalog.as_view(), {'meta_id':75}),
url(r'^blogs/$', BlogList.as_view(), {'meta_id':79}),
url(r'^news/tag/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', NewsTagCatalog.as_view(), {'meta_id':77}),
url(r'^news/tag/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', NewsTagCatalog.as_view(), {'meta_id':76}),
url(r'^news/tag/(?P<slug>.*)/page/(?P<page>\d+)/$', NewsTagCatalog.as_view(), {'meta_id':74}),
url(r'^news/tag/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', NewsTagCatalog.as_view(), {'meta_id':77}),
url(r'^news/tag/(?P<slug>.*)/(?P<year>\d+)/$', NewsTagCatalog.as_view(), {'meta_id':76}),
url(r'^news/tag/(?P<slug>.*)/$', NewsTagCatalog.as_view(), {'meta_id':74}),
url(r'^news/page/(?P<page>\d+)/$', NewsList.as_view(), {'meta_id':78}),
url(r'^news/$', NewsList.as_view(), {'meta_id':78}),
url(r'^blogs/(?P<slug>.*)/$', BlogDetail.as_view(), {'meta_id':19}),
url(r'^news/(?P<slug>.*)/$', NewsDetail.as_view(), {'meta_id':19}),
)

@ -1,10 +1,18 @@
# -*- coding: utf-8 -*-
import json
from django.views.generic import DetailView, ListView
from django.http import HttpResponse
from models import Article
from forms import ArticleFilterForm
from theme.models import Tag
from meta.views import MetadataMixin
class NewsList(ListView):
class NewsList(MetadataMixin, ListView):
model = Article
template_name = 'article/news_list.html'
paginate_by = 10
def get_queryset(self):
if self.request.GET:
@ -14,22 +22,47 @@ class NewsList(ListView):
qs = qs.filter(theme__id__in=themes)
tags = self.request.GET.getlist('tag')
if u'' in tags:
tags.remove(u'')
if tags:
tags = tags[0].split(',')
qs = qs.filter(tag__id__in=tags)
return qs
else:
return self.model.objects.news()
return self.model.objects.news().filter(publish_date__isnull=False).order_by('-publish_date')
class NewsDetail(DetailView):
def get_context_data(self, **kwargs):
context = super(NewsList, self).get_context_data(object_list=self.object_list)
if self.request.GET:
filter_form = ArticleFilterForm(self.request.GET)
tags = self.request.GET.getlist('tag')
if u'' in tags:
tags.remove(u'')
if tags:
tags = tags[0].split(',')
tag_qs = Tag.objects.filter(id__in=tags)
tags = [{'id': str(tag.id), 'text': tag.name} for tag in tag_qs]
filter_form.fields['tag'].widget.attrs['data-predifined'] = json.dumps(tags)
filter_form.fields['tag'].widget.attrs['value'] = ''
else:
filter_form = ArticleFilterForm()
context['article_filter_form'] = filter_form
return context
class NewsDetail(MetadataMixin, DetailView):
model = Article
slug_field = 'slug'
template_name = 'article/news.html'
class BlogList(ListView):
class BlogList(MetadataMixin, ListView):
model = Article
template_name = 'article/blog_list.html'
paginate_by = 10
def get_queryset(self):
if self.request.GET:
@ -40,16 +73,136 @@ class BlogList(ListView):
qs = qs.filter(theme__id__in=themes)
tags = self.request.GET.getlist('tag')
if u'' in tags:
tags.remove(u'')
if tags:
tags = tags[0].split(',')
qs = qs.filter(tag__id__in=tags)
return qs
else:
return self.model.objects.blogs()
def get_context_data(self, **kwargs):
context = super(BlogList, self).get_context_data(object_list=self.object_list)
if self.request.GET:
filter_form = ArticleFilterForm(self.request.GET)
tags = self.request.GET.getlist('tag')
if u'' in tags:
tags.remove(u'')
if tags:
tags = tags[0].split(',')
tag_qs = Tag.objects.filter(id__in=tags)
tags = [{'id': str(tag.id), 'text': tag.name} for tag in tag_qs]
filter_form.fields['tag'].widget.attrs['data-predifined'] = json.dumps(tags)
filter_form.fields['tag'].widget.attrs['value'] = ''
else:
filter_form = ArticleFilterForm()
context['article_filter_form'] = filter_form
return context
class BlogDetail(DetailView):
class BlogDetail(MetadataMixin, DetailView):
model = Article
slug_field = 'slug'
template_name = 'article/article.html'
template_name = 'article/article.html'
from exposition.views import ExpoCatalog
from django.conf import settings
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
class NewsTagCatalog(MetadataMixin, ListView):
model = Article
template_name = 'client/article/catalog.html'
catalog_url = '/news/tag/'
filter_object = None
year = None
month = None
def get_queryset(self):
slug = self.kwargs.get('slug')
tag = get_object_or_404(Tag, url=slug)
self.kwargs['tag'] = tag
self.filter_object = tag
qs = Article.objects.news().filter(tag=tag)
year = self.kwargs.get('year')
if year:
qs = qs.filter(publish_date__year=year)
# info for breadscrumbs
self.year = {'text': year, 'link': '%s%s/%s/'%(self.catalog_url, self.filter_object.url, year)}
month = self.kwargs.get('month')
monthes = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2, 'name': _(u'Февраль')},
'mar': {'value': 3, 'name': _(u'Март')}, 'apr': {'value': 4, 'name': _(u'Апрель')},
'may': {'value': 5, 'name': _(u'Май')}, 'jun': {'value': 6, 'name': _(u'Июнь')},
'jul': {'value': 7, 'name': _(u'Июль')}, 'aug': {'value': 8, 'name': _(u'Август')},
'sep': {'value': 9, 'name': _(u'Сентябрь')}, 'oct': {'value': 10, 'name': _(u'Октябрь')},
'nov': {'value': 11, 'name': _(u'Ноябрь')}, 'dec': {'value': 12, 'name': _(u'Декабрь')}}
if month and monthes.get(month):
qs = qs.filter(publish_date__month=monthes[month]['value'])
self.month = {'text': monthes[month]['name'], 'link': '%s%s/%s/%s/'%(self.catalog_url, self.filter_object.url, year, month)}
return qs
def get_context_data(self, **kwargs):
context = super(NewsTagCatalog, self).get_context_data(**kwargs)
context['filter_object'] = self.filter_object
context['year'] = self.year
context['month'] = self.month
context['catalog_url'] = self.catalog_url
return context
class BlogsTagCatalog(MetadataMixin, ListView):
model = Article
template_name = 'client/article/catalog.html'
catalog_url = '/blogs/tag/'
filter_object = None
year = None
month = None
def get_queryset(self):
slug = self.kwargs.get('slug')
tag = get_object_or_404(Tag, url=slug)
self.kwargs['tag'] = tag
self.filter_object = tag
qs = Article.objects.blogs().filter(tag=tag)
year = self.kwargs.get('year')
if year:
qs = qs.filter(publish_date__year=year)
# info for breadscrumbs
self.year = {'text': year, 'link': '%s%s/%s/'%(self.catalog_url, self.filter_object.url, year)}
month = self.kwargs.get('month')
monthes = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2, 'name': _(u'Февраль')},
'mar': {'value': 3, 'name': _(u'Март')}, 'apr': {'value': 4, 'name': _(u'Апрель')},
'may': {'value': 5, 'name': _(u'Май')}, 'jun': {'value': 6, 'name': _(u'Июнь')},
'jul': {'value': 7, 'name': _(u'Июль')}, 'aug': {'value': 8, 'name': _(u'Август')},
'sep': {'value': 9, 'name': _(u'Сентябрь')}, 'oct': {'value': 10, 'name': _(u'Октябрь')},
'nov': {'value': 11, 'name': _(u'Ноябрь')}, 'dec': {'value': 12, 'name': _(u'Декабрь')}}
if month and monthes.get(month):
qs = qs.filter(publish_date__month=monthes[month]['value'])
self.month = {'text': monthes[month]['name'], 'link': '%s%s/%s/%s/'%(self.catalog_url, self.filter_object.url, year, month)}
return qs
def get_context_data(self, **kwargs):
context = super(BlogsTagCatalog, self).get_context_data(**kwargs)
context['filter_object'] = self.filter_object
context['year'] = self.year
context['month'] = self.month
context['catalog_url'] = self.catalog_url
return context

@ -56,7 +56,7 @@ def city_change(request, url):
else:
#fill form with data from database
data = {'population' : c.population, 'phone_code' : c.phone_code,
'city_id' : city_id}
'city_id' : city_id, 'inflect':c.inflect}
if c.country:
data['country'] = c.country.id

@ -33,6 +33,7 @@ class CityForm(forms.Form):
phone_code = forms.CharField(label='Код города', required=False,
widget=forms.TextInput(attrs={'placeholder':'Код города'}))
code_IATA = forms.ModelChoiceField(label='Код IATA', queryset=Iata.objects.all(), empty_label=None, required=False)
inflect = forms.CharField(label='Inflect', required=False)
#field for comparing tmp files
key = forms.CharField(required=False, widget=forms.HiddenInput())
#
@ -85,6 +86,7 @@ class CityForm(forms.Form):
city.phone_code = data['phone_code']
city.population = data.get('population')
city.inflect = data['inflect']
if data.get('code_IATA'):
city.code_IATA = Iata.objects.get(id=data['code_IATA'].id)# .id cause select uses queryset

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from django.core.management.base import BaseCommand, CommandError
from city.models import City
from country.models import Country
from functions.form_check import translit_with_separator
from django.db import IntegrityError
class Command(BaseCommand):
def handle(self, *args, **options):
qs = City.objects.language('en').filter()
for c in qs:
url = translit_with_separator(c.name.encode('utf8'))
c.url = url
try:
c.save()
except IntegrityError:
continue
print(c.url)
#print(qs.count())

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
import MySQLdb
from MySQLdb.cursors import DictCursor
from django.core.management.base import BaseCommand, CommandError
from django.utils import translation
from country.models import City
class Command(BaseCommand):
def handle(self, *args, **options):
db = MySQLdb.connect(host="localhost",
user="kotzilla",
passwd="qazedc",
db="test2",
charset='utf8',
cursorclass=DictCursor)
cursor = db.cursor()
sql = """SELECT title, url, inflect
FROM old_expomap.products_places
WHERE parent_id > 0 """
cursor.execute(sql)
result = cursor.fetchall()
for res in result:
name = res['title']
url = res['url']
inflect = res['inflect']
City.objects.filter(translations__name=name).update(inflect=inflect, old_url=url)
print(name.encode('utf-8'))

@ -11,10 +11,13 @@ from service.models import Service
from exposition.models import Exposition
from place_exposition.models import PlaceExposition
from organiser.models import Organiser
from conference.models import Conference
from seminar.models import Seminar
from webinar.models import Webinar
# custom functions
from functions.db import db_table_exists
from functions.signal_handlers import post_save_handler
from functions.models_methods import ExpoManager
from functions.models_methods import ExpoManager, CityManager
#check if table exist and create flags if true
flags = [str(item.url) for item in Service.objects.all()] if db_table_exists('service_service') else []
@ -28,11 +31,15 @@ class City(TranslatableModel):
"""
objects = ExpoManager()
used = CityManager()
catalog = '/city/'
services = BitField(flags=flags)
url = models.SlugField(unique=True)
#
old_url = models.CharField(max_length=55)
inflect = models.CharField(max_length=255, blank=True)
#relations
country = models.ForeignKey('country.Country', null=True, on_delete=models.PROTECT, related_name='cities')
code_IATA = models.ForeignKey(Iata, blank=True, null=True)
@ -56,6 +63,9 @@ class City(TranslatableModel):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['translations__name']
def __unicode__(self):
return self.lazy_translation_getter('name', self.pk)
@ -83,7 +93,19 @@ class City(TranslatableModel):
def expositions_number(self):
return len(Exposition.objects.filter(city=self.id))
return Exposition.objects.filter(city=self.id).count()
def conferences_number(self):
return Conference.objects.filter(city=self.id).count()
def seminars_number(self):
return Seminar.objects.filter(city=self.id).count()
def webinars_number(self):
return Webinar.objects.filter(city=self.id).count()
def get_parent(self):
parent = {'text' : self.country.name, 'id': self.country.id, 'name': 'co',

@ -4,6 +4,7 @@ from django.utils.translation import ugettext as _, get_language
from country.models import Country
from city.models import City
from company.models import Company
from theme.models import Theme
class BaseForm(forms.ModelForm):
@ -27,7 +28,7 @@ class NameForm(BaseForm):
class SpecializationForm(BaseForm):
translation = True
specialization = forms.CharField(label=_(u'Описание компании'), widget=forms.TextInput())
specialization = forms.CharField(label=_(u'Описание компании'), widget=forms.TextInput(), required=False)
class Meta:
model = Company._meta.translations_model
fields = ('specialization',)
@ -36,7 +37,7 @@ class SpecializationForm(BaseForm):
class HomeForm(BaseForm):
city = forms.CharField(label='Город', required=False,
widget=forms.HiddenInput(attrs={'class': 'select2'}))
country = forms.ChoiceField(label=_(u'Страна'), choices=[(c.id, c.name) for c in Country.objects.all()], required=False,
country = forms.ChoiceField(label=_(u'Страна'), choices=[('', '')]+[(c.id, c.name) for c in list(Country.objects.all())], required=False,
widget=forms.Select(attrs={'class': 'select2'}))
def __init__(self, *args, **kwargs):
super(HomeForm, self).__init__(*args, **kwargs)
@ -68,6 +69,19 @@ class PhoneForm(BaseForm):
model = Company
fields = ('phone',)
def clean_phone(self):
phone = self.cleaned_data['phone']
if not phone:
return
deduct = ('-','(',')','.',' ', '+')
for elem in deduct:
phone = phone.replace(elem, '')
if phone.isdigit():
return phone
else:
raise forms.ValidationError(_(u'Введите правильный телефон'))
class EmailForm(BaseForm):
email = forms.EmailField(label=_(u'Ваш e-mail'), required=False)
@ -94,12 +108,32 @@ class SocialForm(BaseForm):
fields = ('facebook', 'twitter', 'vk', 'linkedin')
class ThemeForm(BaseForm):
theme = forms.ModelMultipleChoiceField(queryset=Theme.objects.all())
class Meta:
model = Company
fields = ('theme',)
class TagForm(BaseForm):
tag = forms.CharField(required=False, widget=forms.HiddenInput(attrs={'class': 'select2'}))
class Meta:
model = Company
fields = ('tag',)
def clean_tag(self):
tags = self.cleaned_data.get('tag')
if tags:
res = []
for id in tags.split(','):
try:
res.append(int(id))
except:
continue
return res
else:
return []
class FoundationForm(BaseForm):
class Meta:
@ -122,7 +156,7 @@ class DescriptionForm(BaseForm):
class AddressForm(BaseForm):
translation = True
address_inf = forms.CharField(label=_(u'Адрес компании'), widget=forms.TextInput())
address_inf = forms.CharField(label=_(u'Адрес компании'), widget=forms.TextInput(), required=False)
class Meta:
model = Company._meta.translations_model
fields = ('address_inf',)

@ -1,13 +1,21 @@
import json
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.http import HttpResponseRedirect, HttpResponse, Http404, HttpResponseForbidden
from django.utils.translation import get_language
from sorl.thumbnail import get_thumbnail
from edit_forms import *
from accounts.views import ProfileInvalidView
from .models import Company
class BaseView(ProfileInvalidView):
def form_valid(self, form):
company = self.request.user.company
slug = self.kwargs.get('slug')
if not slug:
raise Http404
company = Company.objects.get(url=slug)
if company.creator_id != self.request.user.id:
return HttpResponseForbidden()
if self.form_class.translation:
lang = get_language()
comp_transl = company.translations.get(language_code=lang)
@ -16,8 +24,12 @@ class BaseView(ProfileInvalidView):
else:
form = self.form_class(self.request.POST, instance=company)
form.save()
response = {'success': True}
company = form.save()
try:
rating = company.rating
except AttributeError:
rating = company.master.rating
response = {'success': True, 'rating': rating}
return HttpResponse(json.dumps(response), content_type='application/json')
@ -30,12 +42,19 @@ class LogoView(BaseView):
form_class = LogoForm
def form_valid(self, form):
company = self.request.user.company
#company = self.request.user.company#!!!
slug = self.kwargs.get('slug')
if not slug:
raise Http404
company = Company.objects.get(url=slug)
if company.creator_id != self.request.user.id:
return HttpResponseForbidden()
form = self.form_class(self.request.POST, self.request.FILES, instance=company)
form.save()
company = form.save()
if self.request.is_ajax():
im = get_thumbnail(company.logo, '100x100', crop='center')
response = {'success': True, 'url': im.url}
im = get_thumbnail(company.logo, '100x100', format="PNG")
response = {'success': True, 'url': im.url, 'rating': company.rating}
return HttpResponse(json.dumps(response), content_type='application/json')
else:
return HttpResponseRedirect(company.get_permanent_url())
@ -68,9 +87,56 @@ class SocialView(BaseView):
form_class = SocialForm
class ThemeView(BaseView):
form_class = ThemeForm
def form_valid(self, form):
slug = self.kwargs.get('slug')
if not slug:
raise Http404
company = Company.objects.get(url=slug)
if company.creator_id != self.request.user.id:
return HttpResponseForbidden()
form = self.form_class(self.request.POST, instance=company)
company = form.save()
try:
rating = company.rating
except AttributeError:
rating = company.master.rating
themes = [{'text': item.name,'id': str(item.id),'url': '/members/theme/%s/'%item.url} for item in company.theme.all()]
response = {'success': True, 'rating': rating, 'tags': themes}
return HttpResponse(json.dumps(response), content_type='application/json')
class TagView(BaseView):
form_class = TagForm
def form_valid(self, form):
slug = self.kwargs.get('slug')
if not slug:
raise Http404
company = Company.objects.get(url=slug)
if company.creator_id != self.request.user.id:
return HttpResponseForbidden()
form = self.form_class(self.request.POST, instance=company)
company = form.save()
try:
rating = company.rating
except AttributeError:
rating = company.master.rating
tags = [{'text': item.name,'id': str(item.id),'url': '/members/tag/%s/'%item.url} for item in company.tag.all()]
response = {'success': True, 'rating': rating, 'tags': tags}
return HttpResponse(json.dumps(response), content_type='application/json')
class FoundationView(BaseView):
form_class = FoundationForm

@ -282,6 +282,8 @@ class CreateCompanyForm(forms.Form):
def clean_url(self):
url = self.cleaned_data['url']
url = url.replace('http://expomap.ru/members/', '')
if not is_latin(url):
raise forms.ValidationError(_(u'url должен состоять только из латинских букв'))

@ -119,7 +119,7 @@ class Company(TranslatableModel, ExpoMixin):
def calculate_rating(company):
rating_simple = {'country': 5, 'city': 5, 'address_inf': 10, 'phone': 10, 'fax': 5, 'email': 10,
'facebook': 5, 'twitter': 5, 'linkedin': 5, 'vk': 5, 'web_page': 10, #'logo': 20,
'facebook': 5, 'twitter': 5, 'linkedin': 5, 'vk': 5, 'web_page': 10, 'logo': 20,
'specialization': 5, 'description':15, 'foundation': 5, 'staff_number': 5}# участие и посещение доделать
rating_methods = {'theme': 10, 'tag': 5, 'photo':5}
# base rating
@ -128,7 +128,13 @@ def calculate_rating(company):
if getattr(company, key):
rating += value
themes = company.theme.all().count()
rating += themes * 10
tags = company.tag.all().count()
rating += tags * 10 if tags < 6 else 50
company.rating = rating
# call to prevent recursion
post_save.disconnect(create_company, sender=Company)
company.save()
@ -139,4 +145,11 @@ def create_company(sender, instance, created, **kwargs):
post_save_handler(sender, instance=instance, **kwargs)
calculate_rating(instance)
def calculate_rating_for_translations(sender, instance, created, **kwargs):
company = instance.master
post_save.disconnect(calculate_rating_for_translations, sender=Company._meta.translations_model)
calculate_rating(company)
post_save.connect(calculate_rating_for_translations, sender=Company._meta.translations_model)
post_save.connect(create_company, sender=Company)
post_save.connect(calculate_rating_for_translations, sender=Company._meta.translations_model)

@ -35,4 +35,7 @@ class CompanyExpositionIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchM
def index_queryset(self, using=None):
return self.get_model().objects.filter()
return self.get_model().objects.filter()
def get_updated_field(self):
return 'modified'

@ -1,40 +1,42 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from views import CompanyView, CompanySearchView, MemberDetail, MemberList, MemberTagList, MemberThemeList
from views import CompanySearchView, MemberDetail, MemberList, MemberTagList, MemberThemeList
from django.contrib.auth.decorators import login_required
from edit_views import *
urlpatterns = patterns('',
url(r'company/create-company/$', 'company.views.create_company'),
url(r'company/get-company/$', 'company.views.get_company'),
#
url(r'members/search/$', CompanySearchView.as_view()),
#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()),
url(r'members/theme/(?P<slug>.*)/page/(?P<page>\d+)/$', MemberThemeList.as_view()),
url(r'members/theme/(?P<slug>.*)/$', MemberThemeList.as_view()),
url(r'members/tag/(?P<slug>.*)/page/(?P<page>\d+)/$', MemberTagList.as_view()),
url(r'members/tag/(?P<slug>.*)/$', MemberTagList.as_view()),
url(r'members/page/(?P<page>\d+)/$', MemberList.as_view()),
url(r'members/(?P<slug>.*)/$', MemberDetail.as_view()),
url(r'members/$', MemberList.as_view()),
url(r'members/theme/(?P<slug>.*)/page/(?P<page>\d+)/$', MemberThemeList.as_view(), {'meta_id':69}),
url(r'members/theme/(?P<slug>.*)/$', MemberThemeList.as_view(), {'meta_id':69}),
url(r'members/tag/(?P<slug>.*)/page/(?P<page>\d+)/$', MemberTagList.as_view(), {'meta_id':70}),
url(r'members/tag/(?P<slug>.*)/$', MemberTagList.as_view(), {'meta_id':70}),
url(r'members/page/(?P<page>\d+)/$', MemberList.as_view(), {'meta_id':67}),
url(r'members/(?P<slug>.*)/$', MemberDetail.as_view(), {'meta_id':68}),
url(r'members/$', MemberList.as_view(), {'meta_id':67}),
#
url(r'company/create-company/$', 'company.views.create_company'),
url(r'company/get-company/$', 'company.views.get_company'),
#
url(r'company/update/name/$', login_required(NameView.as_view())),
url(r'^company/update/home/$', login_required(HomeView.as_view())),
url(r'^company/update/specialization/$', login_required(SpecializationView.as_view())),
url(r'^company/update/phone/$', login_required(PhoneView.as_view())),
url(r'^company/update/email/$', login_required(EmailView.as_view())),
url(r'^company/update/web-page/$', login_required(WebPageView.as_view())),
url(r'^company/update/social/$', login_required(SocialView.as_view())),
url(r'^company/update/tag/$', login_required(TagView.as_view())),
url(r'^company/update/foundation/$', login_required(FoundationView.as_view())),
url(r'^company/update/staff/$', login_required(StaffView.as_view())),
url(r'^company/update/description/$', login_required(DescriptionView.as_view())),
url(r'^company/update/address/$', login_required(AddressView.as_view())),
url(r'^company/update/logo/$', login_required(LogoView.as_view())),
url(r'company/update/name/(?P<slug>.*)/$', login_required(NameView.as_view())),
url(r'^company/update/home/(?P<slug>.*)/$', login_required(HomeView.as_view())),
url(r'^company/update/specialization/(?P<slug>.*)/$', login_required(SpecializationView.as_view())),
url(r'^company/update/phone/(?P<slug>.*)/$', login_required(PhoneView.as_view())),
url(r'^company/update/email/(?P<slug>.*)/$', login_required(EmailView.as_view())),
url(r'^company/update/web-page/(?P<slug>.*)/$', login_required(WebPageView.as_view())),
url(r'^company/update/social/(?P<slug>.*)/$', login_required(SocialView.as_view())),
url(r'^company/update/tag/(?P<slug>.*)/$', login_required(TagView.as_view())),
url(r'^company/update/theme/(?P<slug>.*)/$', login_required(ThemeView.as_view())),
url(r'^company/update/foundation/(?P<slug>.*)/$', login_required(FoundationView.as_view())),
url(r'^company/update/staff/(?P<slug>.*)/$', login_required(StaffView.as_view())),
url(r'^company/update/description/(?P<slug>.*)/$', login_required(DescriptionView.as_view())),
url(r'^company/update/address/(?P<slug>.*)/$', login_required(AddressView.as_view())),
url(r'^company/update/logo/(?P<slug>.*)/$', login_required(LogoView.as_view())),
)

@ -15,7 +15,8 @@ from .edit_forms import NameForm as CompNameForm, HomeForm as CompHomeForm, Phon
EmailForm as CompEmailForm, WebPageForm as CompWebPageForm, SocialForm as CompSocialForm,\
TagForm as CompTagForm, DescriptionForm as CompDescr, StaffForm as CompStaff, \
FoundationForm as CompFound, SpecializationForm as CompSpec, AddressForm as CompAddress,\
LogoForm as CompLogo
LogoForm as CompLogo, ThemeForm as CompThemeForm
from meta.views import MetadataMixin
class CompanySearchView(ListView):
@ -51,7 +52,7 @@ class CompanySearchView(ListView):
class MemberList(ListView):
class MemberList(MetadataMixin, ListView):
model = Company
paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/company/companies_list.html'
@ -61,7 +62,7 @@ class MemberList(ListView):
def get_queryset(self):
return self.model.objects.order_by('-rating')
class MemberThemeList(ListView):
class MemberThemeList(MetadataMixin, ListView):
model = Company
paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/company/companies_list.html'
@ -72,11 +73,12 @@ class MemberThemeList(ListView):
qs = super(MemberThemeList, self).get_queryset()
slug = self.kwargs.get('slug')
theme = get_object_or_404(Theme, url=slug)
self.kwargs['theme'] = theme
qs = qs.filter(theme=theme)
return qs
class MemberTagList(ListView):
class MemberTagList(MetadataMixin, ListView):
model = Company
paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/company/companies_list.html'
@ -87,13 +89,15 @@ class MemberTagList(ListView):
qs = super(MemberTagList, self).get_queryset()
slug = self.kwargs.get('slug')
tag = get_object_or_404(Tag, url=slug)
self.kwargs['tag'] = tag
qs = qs.filter(tag=tag)
return qs
class MemberDetail(DetailView):
class MemberDetail(MetadataMixin, DetailView):
model = Company
slug_field = 'url'
template_name = 'client/company/company_detail.html'
@ -108,10 +112,21 @@ class MemberDetail(DetailView):
forms = {
'home_form': CompHomeForm(instance=company), 'phone_form': CompPhoneForm(instance=company),
'email_form': CompEmailForm(instance=company), 'web_page_form': CompWebPageForm(instance=company),
'social_form': CompSocialForm(instance=company), 'tag_form': CompTagForm(instance=company),
'social_form': CompSocialForm(instance=company),
'staff_form': CompStaff(instance=company), 'found_form': CompFound(instance=company),
'logo_form': CompLogo(instance=company)
}
tags = [{'id': str(tag.id), 'text': tag.name, 'url': '/members/tag/%s/'%tag.url} for tag in company.tag.all()]
tag_form = CompTagForm()
tag_form.fields['tag'].widget.attrs['data-predifined'] = json.dumps(tags)
tag_form.fields['tag'].widget.attrs['value'] = ''
#themes = [{'id': str(item.id), 'text': item.name } for item in company.theme.all()]
theme_form = CompThemeForm(instance=company)
#theme_form.fields['theme'].widget.attrs['data-predifined'] = json.dumps(themes)
#theme_form.fields['tag'].widget.attrs['value'] = ''
forms.update({'tag_form': tag_form, 'theme_form': theme_form})
lang = get_language()
comp_transl = company.translations.get(language_code=lang)
@ -125,30 +140,6 @@ class MemberDetail(DetailView):
return context
class CompanyView(ExpoListView):
paginate_by = 10
model = Company
template_name = 'company_catalog.html'
search_form = CompanySearchForm
def get_context_data(self, **kwargs):
context = super(CompanyView, self).get_context_data(**kwargs)
context['type'] = 'members search'
return context
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()
def create_company(request):
response = {'success': False}
@ -166,7 +157,7 @@ def get_company(request):
if request.is_ajax():
term = request.GET['term']
qs = Company.objects.language().filter(translations__name__contains=term).distinct()
result = [{'id': company.id, 'label': company.name} for company in qs]
result = [{'id': company.id, 'label': company.name, 'logo': company.logo.url if company.logo else settings.NO_LOGO } for company in qs]
return HttpResponse(json.dumps(result), content_type='application/json')
else:
return HttpResponse('not ajax')

@ -13,13 +13,14 @@ from forms import ConferenceChangeForm, ConferenceCreateForm, ConferenceDeleteFo
from theme.models import Tag
from city.models import City
from file.models import FileModel, TmpFile
from file.forms import FileModelForm
from file.forms import FileModelForm, FileForm
from photologue.forms import PhotoForm
#python
import random
#custom views
from functions.custom_views import objects_list, delete_object
from functions.views_help import get_referer
from functions.admin_views import AdminListView
from functions.admin_views import AdminListView, AdminView, upload_photo
def conference_all(request):
@ -214,7 +215,84 @@ def conference_change(request, url):
return render_to_response('conference_add.html', args)
class ConferenceView(AdminView):
form_class = ConferenceCreateForm
model = Conference
success_url = '/admin/conference/all/'
template_name = 'admin/conference/conference.html'
def form_valid(self, form):
self.set_obj()
expo = form.save(obj=self.obj)
return HttpResponseRedirect(self.success_url)
def get_form(self, form_class):
if self.request.POST:
return super(ConferenceView, self).get_form(form_class)
obj = self.set_obj()
if obj:
data = {'web_page':obj.web_page, 'foundation_year': obj.foundation_year,
'data_begin':obj.data_begin, 'data_end':obj.data_end, 'currency':obj.currency,
'tax':obj.tax, 'min_price':obj.min_price, 'max_price':obj.max_price,
'link':obj.link, 'conference_id':obj.id, 'expohit': obj.expohit, 'periodic':obj.periodic,
'discount': obj.discount,'canceled': obj.canceled, 'moved': obj.moved,
'visitors': obj.visitors, 'members': obj.members, 'logo': obj.logo,
'audience':[item for item, bool in obj.audience if bool==True],
'quality_label': [item for item, bool in obj.quality_label if bool==True]}
if obj.place:
data['place'] = obj.place.id
data['theme'] = [item.id for item in obj.theme.all()]
data['tag'] = ','.join(['%s:%s'%(item.id, item.name) for item in obj.tag.all()])
data['organiser'] = [item.id for item in obj.organiser.all()]
data['company'] = [item.id for item in obj.company.all()]
data['country'] = obj.country_id
data['city'] = obj.city_id
for code, name in settings.LANGUAGES:
trans_obj = self.model._meta.translations_model.objects.get(language_code = code,master__id=obj.id) #access to translated fields
data['name_%s' % code] = obj.name
data['description_%s' % code] = trans_obj.description
data['main_title_%s' % code] = trans_obj.main_title
data['time_%s' % code] = trans_obj.time
data['main_themes_%s' % code] = trans_obj.main_themes
data['discount_description_%s' % code] = trans_obj.discount_description
data['title_%s' % code] = trans_obj.title
data['keywords_%s' % code] = trans_obj.keywords
data['descriptions_%s' % code] = trans_obj.descriptions
form =form_class(initial=data)
form.fields['city'].widget.attrs['data-init-text'] = obj.city.name
form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.language().filter(theme__in=data['theme'])]
return form
else:
return form_class()
def get_context_data(self, **kwargs):
context = super(ConferenceView, self).get_context_data(**kwargs)
obj = self.set_obj()
if obj:
context['stat_form'] = StatisticForm()
context['file_form'] = FileForm(initial={'model': 'conference.Conference'})
files = FileModel.objects.filter(content_type=ContentType.objects.get_for_model(obj),object_id=getattr(obj, 'id'))
context['files'] = files
context['photo_form'] = PhotoForm()
context['timetable_form'] = TimeTableForm()
context['timetables'] = TimeTable.objects.filter(conference=obj)
return context
class ConferenceListView(AdminListView):
template_name = 'admin/conference/conference_list.html'
form_class = ConferenceFilterForm
model = Conference
model = Conference
def upload_conference_photo(request, conf_id):
return upload_photo(request, conf_id, Conference)

@ -1,13 +1,15 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from admin import ConferenceListView
from admin import ConferenceListView, ConferenceView
urlpatterns = patterns('conference.admin',
url(r'^add.*/$', 'conference_add'),
url(r'^upload-photo/(?P<conf_id>.*)/$', 'upload_conference_photo'),
url(r'^delete/(?P<url>.*)$', 'conference_delete'),
url(r'^change/(?P<url>.*)/$', 'conference_change'),
url(r'^copy/(?P<url>.*)/$', 'conference_copy'),
url(r'^switch/(?P<url>.*)/(?P<action>.*)$', 'conference_switch'),
#url(r'^all/$', 'conference_all'),
url(r'^all/$', ConferenceListView.as_view()),
#url(r'^change/(?P<url>.*)/$', 'conference_change'),
url(r'^switch/(?P<url>.*)/(?P<action>.*)$', 'conference_switch'),
url(r'^(?P<url>.*)/$', ConferenceView.as_view()),
url(r'^$', ConferenceView.as_view()),
)

@ -5,10 +5,10 @@ from ckeditor.widgets import CKEditorWidget
from django.forms.util import ErrorList
from django.core.validators import validate_email, URLValidator
#models
from models import Conference, TimeTable, CURRENCY, Statistic
from models import Conference, TimeTable, CURRENCY, Statistic, BIT_AUDIENCE
from country.models import Country
from city.models import City
from theme.models import Theme
from theme.models import Theme, Tag
from organiser.models import Organiser
from accounts.models import User
from company.models import Company
@ -21,6 +21,9 @@ from functions.files import check_tmp_files
from functions.form_check import translit_with_separator
from functions.admin_forms import AdminFilterForm
places = [(item.id, item.name) for item in PlaceConference.objects.language().all()]
places.insert(0,('', 'Не выбрано'))
class ConferenceCreateForm(forms.Form):
"""
@ -31,18 +34,35 @@ class ConferenceCreateForm(forms.Form):
save function saves data in Conference object. If it doesnt exist create new object
"""
PERIODIC = ((0, u'Не выбрано'),
(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 года'))
public = [(item1, item2) for item1, item2 in BIT_AUDIENCE]
currencies = [(item, item) for item in CURRENCY]
data_begin = forms.DateField(label='Дата начала')
data_end = forms.DateField(label='Дата окночания')
data_begin = forms.DateField(label=u'Дата начала', input_formats=['%Y-%m-%d', '%d.%m.%Y'])
data_end = forms.DateField(label=u'Дата окончания', input_formats=['%Y-%m-%d', '%d.%m.%Y'])
logo = forms.ImageField(label='Logo', required=False)
organiser = forms.MultipleChoiceField(label=u'Организаторы', required=False,
choices=[(item.id, item.name) for item in Organiser.objects.language().all()])
country = forms.ChoiceField(label=u'Страна', choices=[(c.id, c.name) for c in Country.objects.all()])
theme = forms.MultipleChoiceField(label='Тематики',
choices=[(item.id, item.name) for item in Theme.objects.language().all()])
place = forms.ChoiceField(label=u'Место проведения', required=False,
choices=places)
country = forms.ModelChoiceField(label='Страна', queryset=Country.objects.all(), empty_label=None)
theme = forms.ModelMultipleChoiceField(label='Тематики', queryset=Theme.objects.all())
place = forms.ModelChoiceField(label='Место проведения', queryset=PlaceConference.objects.all(),
empty_label='', required=False)
#creates select input with empty choices cause it will be filled with ajax
city = forms.ChoiceField(label='Город', choices=[('','')])
tag = forms.MultipleChoiceField(label='Теги', required=False)
city = forms.CharField(label=u'Город', widget=forms.HiddenInput())
tag = forms.CharField(label=u'Теги', widget=forms.HiddenInput(), required=False)
periodic = forms.ChoiceField(label=u'Периодичность', choices=PERIODIC, required=False)
audience = forms.MultipleChoiceField(label=u'Аудитория', choices=public, initial='', required=False)
web_page = forms.CharField(label='Веб страница', required=False)
link = forms.CharField(label='Линк на регистрацию', required=False)
@ -61,9 +81,7 @@ class ConferenceCreateForm(forms.Form):
quality_label = forms.MultipleChoiceField(label='Тип', required=False,
choices=[('ufi', 'UFI'), ('rsva', 'РСВЯ'), ('exporating', 'ExpoRating')],
widget=forms.CheckboxSelectMultiple())
#field for comparing tmp files
key = forms.CharField(required=False, widget=forms.HiddenInput())
#
conference_id = forms.CharField(required=False, widget=forms.HiddenInput())
@ -99,14 +117,8 @@ class ConferenceCreateForm(forms.Form):
widget=forms.TextInput(attrs={'style':'width: 550px'}))
#!service has bitfield. uncomment when country data will be filled
#services = [(item.id, item.name) for item in Service.objects.all()]
#self.fields['service'] = forms.ChoiceField(label='Услуги', choices=services, required=False)
def save(self, id=None):
def save(self, obj=None):
"""
changes Conference model object with id = id
N/A add new Conference model object
@ -115,15 +127,18 @@ class ConferenceCreateForm(forms.Form):
"""
data = self.cleaned_data
#create new conference object or get exists
if not id:
if not obj:
conference = Conference()
else:
conference = Conference.objects.get(id=id)
conference = obj
conference.theme.clear()
conference.tag.clear()
#simple fields
conference.url = translit_with_separator(data['name_ru'].strip()).lower()
if data.get('logo'):
conference.logo = data['logo']
conference.data_begin = data['data_begin']
conference.data_end = data['data_end']
conference.link = data['link']
@ -141,6 +156,7 @@ class ConferenceCreateForm(forms.Form):
conference.expohit = data['expohit']
conference.canceled = data['canceled']
conference.moved = data['moved']
conference.periodic = data['periodic']
# generates bitfield
flag = 0
if data['quality_label']:
@ -148,32 +164,36 @@ class ConferenceCreateForm(forms.Form):
conference.quality_label = flag
audience = 0
if data['audience']:
audience = reduce(lambda x,y: x|y, (getattr(Conference.audience, item) for item in data['audience']))
conference.audience = audience
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 cause select uses queryset
if data.get('city'):
conference.city = City.objects.get(id=data['city'])
if data.get('place'):
conference.place = PlaceConference.objects.get(id=data['place'].id)#.id cause select uses queryset
conference.place = PlaceConference.objects.get(id=data['place'])
else:
conference.place = None
# fill translated fields and save object
fill_with_signal(Conference, conference, data)
#fill manytomany fields
for item in data['theme']:
conference.theme.add(item.id)#.id cause select uses queryset
conference.theme.add(*data['theme'])
conference.tag.add(*Tag.objects.filter(id__in=data['tag']))
conference.organiser.add(*Organiser.objects.filter(id__in=data.get('organiser', [])))
for item in data['tag']:
conference.tag.add(item)
# uses because in the next loop data will be overwritten
conference.save()
#save files
check_tmp_files(conference, data['key'])
return conference
"""
def clean(self):
id = self.cleaned_data.get('conference_id')
name_ru = self.cleaned_data.get('name_ru')
@ -185,6 +205,20 @@ class ConferenceCreateForm(forms.Form):
del self.cleaned_data['name_ru']
return self.cleaned_data
"""
def clean_tag(self):
tags = self.cleaned_data.get('tag')
if tags:
res = []
for id in tags.split(','):
try:
res.append(int(id))
except:
continue
return res
else:
return []
def clean_web_page(self):
"""

@ -1,8 +1,13 @@
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext as _
from django.db import models
from django.db.models import Q
from django.db.models.signals import post_save, pre_save
from django.contrib.contenttypes import generic
from exposition.manager import ClientManager
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from functions.translate import fill_with_signal
from photologue.models import Gallery
from functions.signal_handlers import post_save_handler, pre_save_handler
import copy
from bitfield import BitField
@ -12,11 +17,14 @@ from functions.db import db_table_exists
from functions.custom_fields import EnumField
from functions.models_methods import ExpoManager
from functions.model_mixin import EventMixin, ExpoMixin
from functions.models_methods import hvad_to_dict
# 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 = [item.url for item in Service.objects.all()] if db_table_exists('service_service') else []
from django.conf import settings
CURRENCY = ('RUB', 'USD', 'EUR')
CURRENCY = settings.CURRENCY
BIT_AUDIENCE = settings.BIT_AUDIENCE
class Conference(TranslatableModel, EventMixin, ExpoMixin):
"""
@ -25,17 +33,23 @@ class Conference(TranslatableModel, EventMixin, ExpoMixin):
Uses hvad.TranslatableModel which is child of django.db.models class
"""
catalog = '/conference/'
catalog_name = _(u'Конференции:')
# type of event
event_type = 'conf'
#set manager of this model
objects = ExpoManager()
enable = ClientManager()
url = models.SlugField(unique=True)
url = models.SlugField(unique=True, max_length=255)
old_url = models.SlugField(unique=True, max_length=255)
data_begin = models.DateField(verbose_name='Дата начала')
data_end = models.DateField(verbose_name='Дата окончания')
services = BitField(flags=flags)
#relations
country = models.ForeignKey('country.Country', verbose_name='Страна', on_delete=models.PROTECT)
city = models.ForeignKey('city.City', verbose_name='Город', on_delete=models.PROTECT)
country = models.ForeignKey('country.Country', verbose_name='Страна', on_delete=models.PROTECT,
related_name='conference_country')
city = models.ForeignKey('city.City', verbose_name='Город', on_delete=models.PROTECT,
related_name='conference_city')
place = models.ForeignKey('place_conference.PlaceConference', verbose_name='Место проведения',
blank=True, null=True, on_delete=models.PROTECT, related_name='conference_place')
theme = models.ManyToManyField('theme.Theme', verbose_name='Тематики',
@ -48,15 +62,20 @@ class Conference(TranslatableModel, EventMixin, ExpoMixin):
blank=True, null=True, related_name='conference_companies')
users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки',
blank=True, null=True, related_name='conference_users')
#!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)
photogallery = models.ForeignKey('photologue.Gallery', blank=True, null=True)
logo = models.ImageField(verbose_name='Logo', upload_to='conference/logo/', blank=True)
rating = models.IntegerField(default=0, db_index=True) # добавить индекс в базе
quality_label = BitField(flags=['ufi', 'rsva', 'exporating'])
periodic = models.FloatField(verbose_name='Переодичность', blank=True, null=True)
audience = BitField(flags=[k for k, v in BIT_AUDIENCE])
web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True)
link = models.CharField(verbose_name='Линк на регистрацию', max_length=255, blank=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='USD')
tax = models.BooleanField(verbose_name='Налог', default=1)
min_price = models.PositiveIntegerField(verbose_name='Минимальная цена', blank=True, null=True)
max_price = models.PositiveIntegerField(verbose_name='Максимальная цена', blank=True, null=True)
@ -69,6 +88,7 @@ class Conference(TranslatableModel, EventMixin, ExpoMixin):
is_published = models.BooleanField(default=0)
files = generic.GenericRelation('file.FileModel', content_type_field='content_type', object_id_field='object_id')
note = generic.GenericRelation('note.Note', 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)
@ -98,54 +118,33 @@ class Conference(TranslatableModel, EventMixin, ExpoMixin):
def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk))
def get_services(self):
country_ids = [item for item, bool in self.country.services if bool==True]
ids = [item for item, bool in self.services if bool==True]
qs = Service.objects.filter(Q(Q(url__in=country_ids) & Q(type=Service.type.conference)) | Q(url__in=ids))
return list(qs)
#return list(Service.objects.language().filter(url__in=ids, type=Service.type.conference).order_by('sort'))
def get_nearest_events(self):
conferences = Conference.objects.all()[:5]
return conferences
def get_catalog_url(self):
return '/conferences/'
def clone(self):
"""
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
# url must be unique
duplicate.url += '_copy'
if Conference.objects.safe_get(url=duplicate.url):
#already has copy this instance
return
# duplicate should not be published
duplicate.is_published = 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()
# but lost all ManyToMany relations and Translations.
# copy relations
for field in self._meta.many_to_many:
source = getattr(self, field.attname)
destination = getattr(duplicate, field.attname)
for item in source.all():
destination.add(item)
return duplicate
return '/conference/'
def get_audience(self):
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_calendar_url(self):
return '/conference-add-calendar/%s/'%self.id
@ -153,12 +152,51 @@ class Conference(TranslatableModel, EventMixin, ExpoMixin):
def get_visit_url(self):
return '/conference-visit/%s/'%self.id
def get_note_by_user(self, user_id):
note = self.note.filter(user__id=user_id)
try:
return note.get().text
except:
return ''
def tags(self):
return self.tag.language().all()
def get_gallery(self):
if self.photogallery:
return self.photogallery
class Statistic(models.Model):
data = {}
model = type(self)
for code, name in settings.LANGUAGES:
obj = model._meta.translations_model.objects.get(language_code = code,master__id=self.id) #access to translated fields
data['title_%s'%code] = obj.name
data['description_%s'%code] = obj.description
gallery = Gallery()
fill_with_signal(Gallery, gallery, data)
self.photogallery = gallery
self.save()
return gallery
class Statistic(TranslatableModel):
conference = models.ForeignKey(Conference, related_name='statistic')
year = models.PositiveIntegerField(verbose_name='Год')
members = models.PositiveIntegerField(verbose_name='Посетители')
visitors = models.PositiveIntegerField(verbose_name='Участники')
members = models.PositiveIntegerField(verbose_name='Посетители', blank=True, null=True)
visitors = models.PositiveIntegerField(verbose_name='Участники', blank=True, null=True)
area = models.PositiveIntegerField(verbose_name='Площадь', blank=True, null=True)
countries_number = models.PositiveIntegerField(verbose_name='Количество стран', blank=True, null=True)
translations = TranslatedFields(
countries = models.TextField(blank=True)
)
def to_dict(self):
return hvad_to_dict(self)
class TimeTable(TranslatableModel):
@ -166,13 +204,27 @@ class TimeTable(TranslatableModel):
TimeTable for business program
"""
exposition = models.ForeignKey(Conference, related_name='business_program')
conference = models.ForeignKey(Conference, related_name='business_program')
begin = models.DateTimeField(verbose_name='Начало')
end = models.DateTimeField(verbose_name='Конец')
timetable_organiser = models.ForeignKey('organiser.Organiser', null=True, blank=True,
related_name='conf_timetable')
#
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
#translated fields
translations = TranslatedFields(
name = models.CharField(verbose_name='Название', max_length=255)
name = models.CharField(verbose_name='Название программы', max_length=255, blank=True),
programe = models.TextField(verbose_name='Программа'),
speaker = models.CharField(verbose_name='Спикеры', max_length=255, blank=True),
place = models.CharField(verbose_name='Место проведения', max_length=255, blank=True)
)
def to_dict(self):
return hvad_to_dict(self)
pre_save.connect(pre_save_handler, sender=Conference)
post_save.connect(post_save_handler, sender=Conference)
post_save.connect(post_save_handler, sender=Conference)
post_save.connect(post_save_handler, sender=TimeTable)
post_save.connect(post_save_handler, sender=Statistic)

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from haystack import indexes
from models import Conference
@ -5,6 +6,32 @@ from models import Conference
class ConferenceIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
where = indexes.MultiValueField()
url = indexes.CharField()
data_begin = indexes.DateField(model_attr='data_begin')
data_end = indexes.DateField(model_attr='data_end')
theme = indexes.MultiValueField()
tag = indexes.MultiValueField()
country_id = indexes.IntegerField()
city_id = indexes.IntegerField()
area_id = indexes.IntegerField()
content_auto = indexes.EdgeNgramField()
form_name = indexes.CharField()
# translated fields
name_en = indexes.CharField()
name_ru = indexes.CharField()
catalog_name_en = indexes.CharField()
catalog_name_ru = indexes.CharField()
def prepare_form_name(self, obj):
return None
def prepare_catalog_name_en(self, obj):
return u'Conferences'
def prepare_catalog_name_ru(self, obj):
return u'Конференции'
def prepare_where(self, obj):
country = [tr.name for tr in obj.country.translations.all()]
city = [tr.name for tr in obj.city.translations.all()]
@ -18,3 +45,5 @@ class ConferenceIndex(indexes.SearchIndex, indexes.Indexable):
return self.get_model().objects.filter(is_published=True)
def get_updated_field(self):
return "modified"

@ -1,15 +1,74 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from views import ConferenceView
from views import ConferenceDetail, ConferenceList, ConferenceByCity, ConferenceByCountry, ConferenceByTheme,\
ConferenceCountryCatalog, ConferenceCityCatalog, ConferenceTagCatalog, ConferenceThemeCatalog, ConferenceMembers,\
ConferenceVisitors, ConferenceServiceView
from exposition.views import ExpositionSearchView
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-note/(?P<slug>.*)/$', 'conference.views.add_note'),
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'),
# search
url(r'conference/search/', ExpositionSearchView.as_view()),
# country catalog
url(r'conference/country/$', ConferenceByCountry.as_view(), {'meta_id':51}),
url(r'conference/country/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ConferenceCountryCatalog.as_view(), {'meta_id':25}),
url(r'conference/country/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ConferenceCountryCatalog.as_view(), {'meta_id':24}),
url(r'conference/country/(?P<slug>.*)/page/(?P<page>\d+)/$', ConferenceCountryCatalog.as_view(), {'meta_id':23}),
url(r'conference/country/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ConferenceCountryCatalog.as_view(), {'meta_id':25}),
url(r'conference/country/(?P<slug>.*)/(?P<year>\d+)/$', ConferenceCountryCatalog.as_view(), {'meta_id':24}),
url(r'conference/country/(?P<slug>.*)/$', ConferenceCountryCatalog.as_view(), {'meta_id':23}),
# city catalog
url(r'conference/city/$', ConferenceByCity.as_view(), {'meta_id':52}),
url(r'conference/city/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ConferenceCityCatalog.as_view(), {'meta_id':28}),
url(r'conference/city/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ConferenceCityCatalog.as_view(), {'meta_id':27}),
url(r'conference/city/(?P<slug>.*)/page/(?P<page>\d+)/$', ConferenceCityCatalog.as_view(), {'meta_id':26}),
url(r'conference/city/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ConferenceCityCatalog.as_view(), {'meta_id':28}),
url(r'conference/city/(?P<slug>.*)/(?P<year>\d+)/$', ConferenceCityCatalog.as_view(), {'meta_id':27}),
url(r'conference/city/(?P<slug>.*)/$', ConferenceCityCatalog.as_view(), {'meta_id':26}),
# theme catalog
url(r'conference/theme/$', ConferenceByTheme.as_view(), {'meta_id':50}),
url(r'conference/theme/(?P<slug>.*)/country/(?P<country_slug>.*)/page/(?P<page>\d+)/$', ConferenceThemeCatalog.as_view()),
url(r'conference/theme/(?P<slug>.*)/country/(?P<country_slug>.*)/$', ConferenceThemeCatalog.as_view()),
url(r'conference/theme/(?P<slug>.*)/city/(?P<city_slug>.*)/page/(?P<page>\d+)/$', ConferenceThemeCatalog.as_view()),
url(r'conference/theme/(?P<slug>.*)/city/(?P<city_slug>.*)/$', ConferenceThemeCatalog.as_view()),
url(r'conference/theme/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ConferenceThemeCatalog.as_view(), {'meta_id':31}),
url(r'conference/theme/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ConferenceThemeCatalog.as_view(), {'meta_id':30}),
url(r'conference/theme/(?P<slug>.*)/page/(?P<page>\d+)/$', ConferenceThemeCatalog.as_view(), {'meta_id':29}),
url(r'conference/theme/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ConferenceThemeCatalog.as_view(), {'meta_id':31}),
url(r'conference/theme/(?P<slug>.*)/(?P<year>\d+)/$', ConferenceThemeCatalog.as_view(), {'meta_id':30}),
url(r'conference/theme/(?P<slug>.*)/$', ConferenceThemeCatalog.as_view(), {'meta_id':29}),
# tag catalog
url(r'conference/tag/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ConferenceTagCatalog.as_view(), {'meta_id':34}),
url(r'conference/tag/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ConferenceTagCatalog.as_view(), {'meta_id':33}),
url(r'conference/tag/(?P<slug>.*)/page/(?P<page>\d+)/$', ConferenceTagCatalog.as_view(), {'meta_id':32}),
url(r'conference/tag/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ConferenceTagCatalog.as_view(), {'meta_id':34}),
url(r'conference/tag/(?P<slug>.*)/(?P<year>\d+)/$', ConferenceTagCatalog.as_view(), {'meta_id':33}),
url(r'conference/tag/(?P<slug>.*)/$', ConferenceTagCatalog.as_view(), {'meta_id':32}),
# conf additional pages
url(r'conference/(?P<slug>.*)/visitors/page/(?P<page>\d+)/$', ConferenceVisitors.as_view()),
url(r'conference/(?P<slug>.*)/visitors/$', ConferenceVisitors.as_view()),
url(r'conference/(?P<slug>.*)/members/page/(?P<page>\d+)/$', ConferenceMembers.as_view()),
url(r'conference/(?P<slug>.*)/members/$', ConferenceMembers.as_view()),
url(r'conference/(?P<slug>.*)/service/(?P<service_url>.*)/', ConferenceServiceView.as_view()),
# conf list
url(r'conference/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ConferenceList.as_view(), {'meta_id':22}),
url(r'conference/(?P<year>\d+)/page/(?P<page>\d+)/$', ConferenceList.as_view(), {'meta_id':21}),
url(r'conference/(?P<year>\d+)/(?P<month>.*)/$', ConferenceList.as_view(), {'meta_id':22}),
url(r'conference/(?P<year>\d+)/$', ConferenceList.as_view(), {'meta_id':21}),
url(r'conference/page/(?P<page>\d+)/$', ConferenceList.as_view(), {'meta_id':20}),
# conf page
url(r'conference/(?P<slug>.*)/$', ConferenceDetail.as_view(), {'meta_id':35}),
url(r'conference/$', ConferenceList.as_view(), {'meta_id':20}),
)
"""
"""

@ -1,12 +1,387 @@
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from models import Conference
from functions.custom_views import ExpoListView
import json
import datetime
from django.conf import settings
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.contrib import messages
from django.shortcuts import get_object_or_404
from django.contrib.contenttypes.models import ContentType
from django.views.generic import ListView, DetailView
from django.views.generic.edit import FormMixin
from django.utils.translation import ugettext as _
from django.utils import translation
from note.models import Note
from models import Conference
from accounts.models import User
from country.models import Country
from city.models import City
from theme.models import Theme, Tag
from service.order_forms import AdvertiseForm
from functions.search_forms import ExpositionSearchForm
from meta.views import MetadataMixin
from functions.cache_mixin import JitterCacheMixin, CacheMixin
MONTHES = settings.MONTHES
class ConferenceBy(JitterCacheMixin, MetadataMixin, ListView):
cache_range = settings.CACHE_RANGE
template_name = 'conference/conference_by.html'
title1 = ''
title2 = ''
"""
abstact class
"""
def get_context_data(self, **kwargs):
context = super(ConferenceBy, self).get_context_data(**kwargs)
context.update({'title1': self.title1, 'title2': self.title2, 'catalog': self.catalog})
return context
class ConferenceByCountry(ConferenceBy):
model = Country
title1 = _(u'По странам')
title2 = _(u'Коференции мира по странам')
catalog = 'country/'
def get_queryset(self):
return self.model.objects.conference_countries_with_count()
#lang = translation.get_language()
#return self.model.objects.select_related('conference_country')\
# .filter(conference_country__country__isnull=False, translations__language_code=lang)\
# .order_by('translations__name').distinct()
class ConferenceByTheme(ConferenceBy):
model = Theme
title1 = _(u'По тематикам')
title2 = _(u'Коференции мира по тематикам')
catalog = 'theme/'
def get_queryset(self):
return self.model.active.conference_themes_with_count()
#lang = translation.get_language()
#return self.model.objects.select_related('conference_themes')\
# .filter(conference_themes__theme__isnull=False, translations__language_code=lang)\
# .order_by('translations__name').distinct()
class ConferenceByCity(ConferenceBy):
model = City
title1 = _(u'По городам')
title2 = _(u'Коференции мира по городам')
catalog = 'city/'
def get_queryset(self):
return self.model.used.conference_cities_with_count()
#lang = translation.get_language()
#return self.model.objects.select_related('conference_city')\
# .filter(conference_city__city__isnull=False, translations__language_code=lang)\
# .order_by('translations__name').distinct()
class ConferenceCatalog(JitterCacheMixin, MetadataMixin, ListView):
cache_range = settings.CACHE_RANGE
model = Conference
paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/conference/catalog.html'
search_form = ExpositionSearchForm
filter_object = None
year = None
month = None
country = None
city = None
def get_filtered_qs(self):
# diferent for views
pass
def get_queryset(self):
qs = self.get_filtered_qs()
year = self.kwargs.get('year')
if year:
qs = self.model.enable.filter(data_end__year=year)
filter_object = self.filter_object
if isinstance(filter_object, Country):
qs = qs.filter(country=filter_object)
elif isinstance(filter_object, City):
qs = qs.filter(city=filter_object)
elif isinstance(filter_object, Theme):
qs = qs.filter(theme=filter_object)
if self.kwargs.get('country'):
qs = qs.filter(country=self.kwargs.get('country'))
if self.kwargs.get('city'):
qs = qs.filter(city=self.kwargs.get('city'))
elif isinstance(filter_object, Tag):
qs = qs.filter(tag=filter_object)
# info for breadscrumbs
self.year = {'text': year, 'link': '%s%s/%s/'%(self.catalog_url, self.filter_object.url, year)}
month = self.kwargs.get('month')
monthes = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2, 'name': _(u'Февраль')},
'mar': {'value': 3, 'name': _(u'Март')}, 'apr': {'value': 4, 'name': _(u'Апрель')},
'may': {'value': 5, 'name': _(u'Май')}, 'jun': {'value': 6, 'name': _(u'Июнь')},
'jul': {'value': 7, 'name': _(u'Июль')}, 'aug': {'value': 8, 'name': _(u'Август')},
'sep': {'value': 9, 'name': _(u'Сентябрь')}, 'oct': {'value': 10, 'name': _(u'Октябрь')},
'nov': {'value': 11, 'name': _(u'Ноябрь')}, 'dec': {'value': 12, 'name': _(u'Декабрь')}}
if month and monthes.get(month):
qs = qs.filter(data_begin__month=monthes[month]['value'])
if self.country:
self.month = {'text': monthes[month]['name'], 'link': '%s%s/country/%s/%s/%s/'%
(self.catalog_url, self.filter_object.url, self.country.url, year, month)}
elif self.city:
self.month = {'text': monthes[month]['name'], 'link': '%s%s/city/%s/%s/%s/'%
(self.catalog_url, self.filter_object.url, self.city.url, year, month)}
else:
self.month = {'text': monthes[month]['name'], 'link': '%s%s/%s/%s/'%(self.catalog_url, self.filter_object.url, year, month)}
return qs.order_by('data_begin')
def get_context_data(self, **kwargs):
context = super(ConferenceCatalog, self).get_context_data(**kwargs)
context['search_form'] = self.search_form
context['filter_object'] = self.filter_object
context['year'] = self.year
context['month'] = self.month
context['catalog_url'] = self.catalog_url
return context
class ConferenceCountryCatalog(ConferenceCatalog):
catalog_url = '/conference/country/'
def get_filtered_qs(self):
#this method used in parent get_queryset
slug = self.kwargs.get('slug')
country = get_object_or_404(Country, url=slug)
self.kwargs['country'] = country
self.filter_object = country
qs = self.model.enable.upcoming().filter(country=country)
return qs
class ConferenceCityCatalog(ConferenceCatalog):
catalog_url = '/conference/city/'
def get_filtered_qs(self):
#this method used in parent get_queryset
slug = self.kwargs.get('slug')
city = get_object_or_404(City, url=slug)
self.kwargs['city'] = city
qs = self.model.enable.upcoming().filter(city=city)
self.filter_object = city
return qs
class ConferenceThemeCatalog(ConferenceCatalog):
template_name = 'conference/catalog_theme.html'
catalog_url = '/conference/theme/'
country = None
city = None
def get_filtered_qs(self):
#this method used in parent get_queryset
slug = self.kwargs.get('slug')
country_slug = self.kwargs.get('country_slug')
city_slug = self.kwargs.get('city_slug')
theme = get_object_or_404(Theme, url=slug)
self.kwargs['theme'] = theme
qs = self.model.enable.upcoming().filter(theme=theme)
if country_slug:
country = get_object_or_404(Country, url=country_slug)
self.country = country
qs = qs.filter(country=country)
if city_slug:
city = get_object_or_404(City, url=city_slug)
self.city = city
qs = qs.filter(city=city)
self.filter_object = theme
return qs
def get_context_data(self, **kwargs):
context = super(ConferenceThemeCatalog, self).get_context_data(**kwargs)
if self.country:
context['country'] = self.country
if self.city:
context['city'] = self.city
return context
class ConferenceTagCatalog(ConferenceCatalog):
catalog_url = '/conference/tag/'
def get_filtered_qs(self):
#this method used in parent get_queryset
slug = self.kwargs.get('slug')
tag = get_object_or_404(Tag, url=slug)
self.kwargs['tag'] = tag
qs = self.model.enable.upcoming().filter(tag=tag)
self.filter_object = tag
return qs
class ConferenceVisitors(MetadataMixin, ListView):
paginate_by = settings.CLIENT_PAGINATION
model = Conference
#template_name = 'event_visitors.html'
template_name = 'client/conference/visitors.html'
obj = None
search_form = ExpositionSearchForm
def get_queryset(self):
slug = self.kwargs.get('slug')
conference = get_object_or_404(self.model, url=slug)
self.obj = conference
return conference.users.all()
def get_context_data(self, **kwargs):
context = super(ConferenceVisitors, self).get_context_data(**kwargs)
context['object'] = self.obj
context['search_form'] = self.search_form
return context
class ConferenceMembers(MetadataMixin, ListView):
paginate_by = settings.CLIENT_PAGINATION
model = Conference
#template_name = 'event_visitors.html'
template_name = 'client/conference/members.html'
obj = None
search_form = ExpositionSearchForm
def get_queryset(self):
slug = self.kwargs.get('slug')
conference = get_object_or_404(self.model, url=slug)
self.obj = conference
return conference.company.all()
def get_context_data(self, **kwargs):
context = super(ConferenceMembers, self).get_context_data(**kwargs)
context['object'] = self.obj
context['search_form'] = self.search_form
return context
from service.models import Service
from service.views import order_forms
class ConferenceServiceView(FormMixin, DetailView):
model = Conference
slug_field = 'url'
service = None
success_url = '/service/thanks/'
def post(self, request, *args, **kwargs):
self.object = self.get_object()
service_url = self.kwargs.get('service_url')
service = get_object_or_404(Service, url=service_url)
service_form = order_forms.get(service_url)
self.form_class = service_form
form = self.get_form(service_form)
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def get_context_data(self, **kwargs):
context = super(ConferenceServiceView, self).get_context_data(**kwargs)
service_url = self.kwargs.get('service_url')
service = get_object_or_404(Service, url=service_url)
self.service = service
self.template_name = service.template
form = order_forms.get(service_url)
self.form_class = form
if not form:
raise Http404
context['form'] = self.get_form(self.form_class)
context['service'] = service
context['object'] = self.get_object()
return context
def form_valid(self, form):
order = form.save(commit=False)
order.conference = self.object
order.save()
messages.success(self.request, _(u'Ваш запрос был успешно отправлен'))
return HttpResponseRedirect(self.success_url)
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
"""
if self.request.user.is_authenticated():
user = self.request.user
initial = {'person_inf': user.get_full_name(),
'person': user.email,
'country': user.profile.country.name if user.profile.country else '',
'city':user.profile.city.name if user.profile.city else '',
'phone': user.profile.phone if user.profile.phone else ''}
class ConferenceView(ExpoListView):
return initial
else:
return self.initial.copy()
class ConferenceDetail(JitterCacheMixin, DetailView):
cache_range = settings.CACHE_RANGE
model = Conference
template_name = 'event_catalog.html'
slug_field = 'url'
template_name = 'client/conference/conference_detail.html'
def get_context_data(self, **kwargs):
context = super(ConferenceDetail, self).get_context_data(**kwargs)
context['advertising_form'] = AdvertiseForm()
return context
class ConferenceList(MetadataMixin, JitterCacheMixin, ListView):
cache_range = settings.CACHE_RANGE
model = Conference
paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/conference/conference_list.html'
search_form = ExpositionSearchForm
catalog_url = '/conference/'
year = None
month = None
def get_queryset(self):
if self.request.user.is_staff:
qs = self.model.objects.upcoming()
else:
qs = self.model.enable.upcoming()
year = self.kwargs.get('year')
if year:
qs = self.model.enable.filter(data_end__year=year)
# info for breadscrumbs
self.year = {'text': year, 'link': '%s%s/'%(self.catalog_url, year)}
month = self.kwargs.get('month')
if month and MONTHES.get(month):
qs = qs.filter(data_begin__month=MONTHES[month]['value'])
self.month = {'text': MONTHES[month]['name'], 'link': '%s%s/%s/'%(self.catalog_url, year, month)}
return qs
def get_context_data(self, **kwargs):
context = super(ConferenceList, self).get_context_data(**kwargs)
context['month'] = self.month
context['catalog_url'] = self.catalog_url
context['search_form'] = self.search_form
context['year'] = self.year
context['month'] = self.month
return context
def conference_add_calendar(request, id):
args = {'success': False}
@ -14,38 +389,32 @@ def conference_add_calendar(request, id):
if user.is_authenticated():
conf = Conference.objects.safe_get(id=id)
if conf:
if conf in user.calendar.get_confs():
user.calendar.conferences.remove(conf)
args['in'] = False
else:
user.calendar.conferences.add(conf)
args['success'] = True
else:
args['not_authorized'] = True
args['in'] = 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:
if user in conf.users.all():
conf.users.remove(user)
args['in'] = False
else:
conf.users.add(user)
args['success'] = True
args['in'] = True
args['success'] = True
else:
args['not_authorized'] = True
@ -53,18 +422,34 @@ def conference_visit(request, id):
return HttpResponse(json.dumps(args), content_type='application/json')
def conference_unvisit(request, id):
def add_note(request, slug):
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')
if request.user.is_authenticated():
if request.GET:
text = request.GET['note_text']
try:
conf = Conference.objects.get(url=slug)
except Conference.DoesNotExist:
raise Http404
ct = ContentType.objects.get_for_model(conf)
object_id = conf.id
user = User.objects.get(id=request.user.id)
if Note.objects.filter(user=user, content_type=ct, object_id=object_id).exists():
Note.objects.filter(user=user, content_type=ct, object_id=object_id).update(text=text)
else:
Note.objects.create(content_type=ct, object_id=object_id, user=user, text=text)
user.calendar.conferences.add(conf)
args['success'] = True
args['text'] = text
else:
args['not_authorized'] = True
args['success'] = True
return HttpResponse(json.dumps(args), content_type='application/json')

@ -1,23 +1,25 @@
import json
from django.views.generic import TemplateView
from django.shortcuts import HttpResponse
from forms import CallbackForm
#from forms import CallbackForm
from service.order_forms import CallBackForm
from meta.views import MetadataMixin
class AdvertisingView(TemplateView):
class AdvertisingView(MetadataMixin, TemplateView):
template_name = 'simple_pages/advertising.html'
class AboutView(TemplateView):
class AboutView(MetadataMixin, TemplateView):
template_name = 'simple_pages/about.html'
def callback(request):
response = {'success': False}
if request.GET:
form = CallbackForm(request.GET)
form = CallBackForm(request.GET)
if form.is_valid():
form.send()
form.save()
response['success'] = True
else:
response['errors'] = form.errors

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
import MySQLdb
from MySQLdb.cursors import DictCursor
from django.core.management.base import BaseCommand, CommandError
from django.utils import translation
from country.models import Country
def get_from_old(country):
db = MySQLdb.connect(host="localhost",
user="kotzilla",
passwd="qazedc",
db="test2",
charset='utf8',
cursorclass=DictCursor)
cursor = db.cursor()
sql = """SELECT url, inflect FROM old_expomap.products_places WHERE title="%(name)s" """%{'name': country.name.encode('utf-8')}
#print(country.name.encode('utf-8'))
# print(sql)
cursor.execute(sql)
result = cursor.fetchone()
return result
class Command(BaseCommand):
def handle(self, *args, **options):
translation.activate('ru')
for country in Country.objects.all():
old_data = get_from_old(country)
if old_data is None:
continue
country.old_url = old_data['url']
country.inflect = old_data['inflect']
try:
country.save()
print(country)
except:
continue

@ -0,0 +1,105 @@
import datetime
from django.utils import translation
from django.core.cache import cache
from django.utils.translation import get_language as lang
from hvad.models import TranslationManager
class CountryManager(TranslationManager):
cache_time = 600
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
def expo_countries(self):
lang = translation.get_language()
key = 'used_expo_countries_%s'%lang
cached_countries = cache.get(key)
if cached_countries:
return cached_countries
else:
from exposition.models import Exposition
countries_id = [item['country_id'] for item in Exposition.objects.values('country_id').distinct()]
countries = list(self.language().filter(id__in=countries_id))
cache.set(key, countries, self.cache_time)
return countries
def expo_countries_with_count(self):
lang = translation.get_language()
key = 'used_expo_countries_count_%s'%lang
cached_countries = cache.get(key)
if cached_countries:
return cached_countries
else:
from exposition.models import Exposition
sql = {'expo_count':
"""SELECT COUNT(*)
FROM exposition_exposition
WHERE exposition_exposition.country_id = country_country.id
AND exposition_exposition.data_end >= CURDATE()
AND exposition_exposition.is_published = 1"""}
now = datetime.datetime.now().date()
# id of unique countries
countries_id = [item['country_id'] for item in Exposition.objects.filter(is_published=True, data_end__gte=now).values('country_id').distinct()]
countries = set(list(self.language().filter(id__in=countries_id).extra(select=sql)))
countries = sorted(countries, key=lambda x: x.name)
cache.set(key, countries, self.cache_time)
return countries
def conference_countries_with_count(self):
lang = translation.get_language()
key = 'used_conference_countries_count_%s'%lang
cached_countries = cache.get(key)
if cached_countries:
return cached_countries
else:
from conference.models import Conference
sql = {'conference_count':
"""SELECT COUNT(*)
FROM conference_conference
WHERE conference_conference.country_id = country_country.id
AND conference_conference.data_end >= CURDATE()
AND conference_conference.is_published = 1"""}
now = datetime.datetime.now().date()
# id of unique countries
countries_id = [item['country_id'] for item in Conference.objects.filter(is_published=True, data_end__gte=now).values('country_id').distinct()]
countries = set(list(self.language().filter(id__in=countries_id).extra(select=sql)))
countries = sorted(countries, key=lambda x: x.name)
cache.set(key, countries, self.cache_time)
return countries
def conference_countries(self):
lang = translation.get_language()
key = 'used_conference_countries_%s'%lang
cached_countries = cache.get(key)
if cached_countries:
return cached_countries
else:
from conference.models import Conference
countries_id = [item['country_id'] for item in Conference.objects.values('country_id').distinct()]
countries = list(self.language().filter(id__in=countries_id))
cache.set(key, countries, self.cache_time)
return countries
class AreaManager(TranslationManager):
def all_sorted(self):
"""
return list, not queryset
"""
model = self.model
result = list(model.objects.filter())
result.sort(key=lambda x: len(x.expos()), reverse=True)
return result

@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
from datetime import date
from django.db import models
from django.utils.translation import ugettext as _
from django.contrib.contenttypes import generic
from django.db.models.signals import post_save, pre_save
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from django.db.models.signals import post_save
from hvad.models import TranslatableModel, TranslatedFields
from bitfield import BitField
from manager import CountryManager, AreaManager
# models
from directories.models import Language, Currency
from city.models import City
@ -13,42 +13,18 @@ from service.models import Service
from exposition.models import Exposition
from place_exposition.models import PlaceExposition
from organiser.models import Organiser
from conference.models import Conference
from seminar.models import Seminar
from webinar.models import Webinar
# func
from functions.custom_fields import EnumField
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
from django.utils import translation
# check if table exist and create flags if true
flags = [str(item.url) for item in Service.objects.all()] if db_table_exists('service_service') else []
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 AreaManager(TranslationManager):
def all_sorted(self):
"""
return list, not queryset
"""
model = self.model
result = list(model.objects.filter())
result.sort(key=lambda x: len(x.expos()), reverse=True)
return result
class Area(TranslatableModel):
translations = TranslatedFields(
@ -56,13 +32,16 @@ class Area(TranslatableModel):
)
objects = AreaManager()
class Meta:
ordering = ['translations__name']
def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk))
def countries(self):
lang = translation.get_language()
return Country.objects.select_related('exposition_country')\
.filter(exposition_country__country__isnull=False, translations__language_code=lang, area=self).distinct()
.filter(exposition_country__country__isnull=False, translations__language_code=lang, area=self).distinct().order_by('translations__name')
def expos(self):
countries = self.countries()
@ -77,9 +56,6 @@ class Area(TranslatableModel):
return parent
class Country(TranslatableModel):
"""
Create Country model
@ -87,12 +63,12 @@ class Country(TranslatableModel):
Uses hvad.TranslatableModel which is child of django.db.models class
"""
objects = CountryManager()
catalog = '/country/'
services = BitField(flags=flags)
url = models.SlugField(unique=True)
old_url = models.CharField(unique=True, max_length=55)
inflect = models.CharField(max_length=255, blank=True)
# relations
area = models.ForeignKey(Area)
big_cities = models.ManyToManyField(City, blank=True, null=True, related_name='cities')
@ -104,14 +80,12 @@ class Country(TranslatableModel):
teritory = models.PositiveIntegerField(blank=True, null=True)
timezone = models.FloatField(blank=True, null=True)
phone_code = models.PositiveIntegerField(blank=True, null=True)
time_delivery = models.PositiveSmallIntegerField(blank=True, null=True)
latitude = models.FloatField(blank=True, null=True)
longitude = models.FloatField(blank=True, null=True)
# fields saves information about creating and changing model
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
country_code = models.CharField(max_length=2)
# connection with FileModel by ContentType
files = generic.GenericRelation('file.FileModel',content_type_field='content_type', object_id_field='object_id')
#translated fields
@ -127,12 +101,10 @@ class Country(TranslatableModel):
title = models.CharField(max_length=255),
descriptions = models.CharField(max_length=255),
keywords = models.CharField(max_length=255),
)
country_code = models.CharField(max_length=2)
# class Meta:
# ordering = ['translations__name']
class Meta:
ordering = ['translations__name']
def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk))
@ -160,10 +132,24 @@ class Country(TranslatableModel):
return len(Exposition.objects.filter(country=self.id))
def conferences_number(self):
return Conference.objects.filter(country=self.id).count()
def seminars_number(self):
return Seminar.objects.filter(country=self.id).count()
def webinars_number(self):
return Webinar.objects.filter(country=self.id).count()
def active_cities(self):
return City.used.active_qs().filter(country=self)
lang = translation.get_language()
return City.objects.select_related('exposition_city')\
.filter(exposition_city__city__isnull=False, translations__language_code=lang, country=self).distinct()
#return City.objects.select_related('exposition_city')\
# .filter(exposition_city__city__isnull=False, translations__language_code=lang, country=self).distinct().order_by('translations__name')
def get_sub_categories(self):
objects = [{'text':item.name, 'id':item.id, 'name':'ci', 'sub': False} for item in self.active_cities()]

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import json
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.core.context_processors import csrf
@ -8,6 +9,7 @@ from django.forms.models import modelformset_factory
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.decorators import login_required
# models and forms
from haystack.query import SearchQuerySet
from models import Exposition, TimeTable, Statistic, TmpTimeTable
from forms import ExpositionCreateForm, ExpositionDeleteForm, TimeTableForm, StatisticForm, ExpositionFilterForm
from theme.models import Tag
@ -241,11 +243,11 @@ class ExpositionView(AdminView):
template_name = 'admin/exposition/exposition.html'
def form_valid(self, form):
StatisticFormSet = formset_factory(StatisticForm)
formset_statistic = StatisticFormSet(self.request.POST)
#StatisticFormSet = formset_factory(StatisticForm)
#formset_statistic = StatisticFormSet(self.request.POST)
self.set_obj()
expo = form.save(obj=self.obj)
"""
# delete old halls
Statistic.objects.filter(exposition=getattr(expo, 'id')).delete()
@ -255,7 +257,7 @@ class ExpositionView(AdminView):
statistic = item.save(commit=False)
statistic.exposition = expo
statistic.save()
"""
return HttpResponseRedirect(self.success_url)
@ -331,20 +333,22 @@ class ExpositionView(AdminView):
context = super(ExpositionView, self).get_context_data(**kwargs)
obj = self.set_obj()
if obj:
StatisticFormSet = modelformset_factory(Statistic, form=StatisticForm, exclude=('exposition',))
#StatisticFormSet = modelformset_factory(Statistic, form=StatisticForm, exclude=('exposition',))
# get existing statistic
statistic = Statistic.objects.filter(exposition=getattr(obj, 'id'))
#statistic = Statistic.objects.filter(exposition=getattr(obj, 'id'))
# fill HallFormSet
formset_statistic = StatisticFormSet(queryset=statistic)
#formset_statistic = StatisticFormSet(queryset=statistic)
context['stat_form'] = StatisticForm()
context['file_form'] = FileForm(initial={'model': 'exposition.Exposition'})
files = FileModel.objects.filter(content_type=ContentType.objects.get_for_model(obj),object_id=getattr(obj, 'id'))
context['files'] = files
else:
StatisticFormSet = formset_factory(StatisticForm)
formset_statistic = StatisticFormSet()
#StatisticFormSet = formset_factory(StatisticForm)
#formset_statistic = StatisticFormSet()
pass
context['formset_statistic'] = formset_statistic
#context['formset_statistic'] = formset_statistic
context['photo_form'] = PhotoForm()
context['timetable_form'] = TimeTableForm()
@ -358,4 +362,26 @@ class ExpositionListView(AdminListView):
def upload_exposition_photo(request, expo_id):
return upload_photo(request, expo_id, Exposition)
return upload_photo(request, expo_id, Exposition)
def get_by_lang(item, field, lang='en'):
"""
:param item: searchresult object
field: translated field
:return:
"""
return getattr(item, field+'_'+lang)
from django.utils import translation
def search_expo(request):
term = request.GET['term'].capitalize()
lang = translation.get_language()
if not term:
qs = SearchQuerySet().models(Exposition).order_by('text')[:30]
else:
qs = SearchQuerySet().models(Exposition).autocomplete(content_auto=term).order_by('text')[:30]
result = [{'id': item.pk, 'label': get_by_lang(item, 'name', lang)} for item in qs]
return HttpResponse(json.dumps(result), content_type='application/json')

@ -6,13 +6,16 @@ urlpatterns = patterns('exposition.admin',
url(r'^upload-photo/(?P<expo_id>.*)/$', 'upload_exposition_photo'),
#url(r'^add.*/$', 'exposition_add'),
#url(r'^delete/(?P<url>.*)/$', 'exposition_delete'),
url(r'^delete/(?P<url>.*)/$', 'exposition_delete'),
#url(r'^change/(?P<url>.*)/$', 'exposition_change'),
url(r'^all/$', ExpositionListView.as_view()),
url(r'^switch/(?P<url>.*)/(?P<action>.*)$', 'exposition_switch'),
#url(r'^copy/(?P<url>.*)$', 'exposition_copy'),
url(r'^search/$', 'search_expo'),
url(r'^(?P<url>.*)/$', ExpositionView.as_view()),
url(r'^$', ExpositionView.as_view()),
)

@ -28,6 +28,8 @@ from functions.admin_forms import AdminFilterForm
places = [(item.id, item.name) for item in PlaceExposition.objects.language().all()]
places.insert(0,('', 'Не выбрано'))
class ExpositionCreateForm(forms.Form):
"""
Create Exposition form for creating exposition
@ -44,7 +46,7 @@ class ExpositionCreateForm(forms.Form):
currencies = [(item, item) for item in CURRENCY]
data_begin = forms.DateField(label=u'Дата начала', input_formats=['%Y-%m-%d', '%d.%m.%Y'])
data_end = forms.DateField(label=u'Дата окночания', input_formats=['%Y-%m-%d', '%d.%m.%Y'])
data_end = forms.DateField(label=u'Дата окончания', input_formats=['%Y-%m-%d', '%d.%m.%Y'])
logo = forms.ImageField(label='Logo', required=False)
organiser = forms.MultipleChoiceField(label=u'Организаторы', required=False,
@ -77,13 +79,9 @@ class ExpositionCreateForm(forms.Form):
widget=forms.CheckboxSelectMultiple())
#
currency = forms.ChoiceField(label=u'Валюта', choices=currencies, required=False)
application_deadline = forms.DateField(label=u'Срок подачи стэнда', required=False)
min_stand_size = forms.CharField(label=u'Минимальный размер стэнда', required=False)
application_deadline = forms.DateField(label=u'Срок подачи стенда', required=False)
min_stand_size = forms.CharField(label=u'Минимальный размер стенда', required=False)
#price_day = forms.CharField(label=u'Цена за 1 день', required=False)
#price_all = forms.CharField(label=u'Цена за все дни', required=False)
#price_day_bar = forms.CharField(label=u'Цена на стойке 1 день', required=False)
#price_all_bar = forms.CharField(label=u'Цена на стойке все дни', required=False)
price_catalog = forms.CharField(label=u'Цена за каталог', required=False)
tax = forms.BooleanField(label=u'Налог включен', initial=True, required=False)
min_closed_area = forms.CharField(label=u'Минимальная цена закрытой НЕ оборудованной площади', required=False)
@ -227,6 +225,8 @@ class ExpositionCreateForm(forms.Form):
if data.get('place'):
exposition.place = PlaceExposition.objects.get(id=data['place'])
else:
exposition.place = None
# fill translated fields and save object
fill_with_signal(Exposition, exposition, data)
@ -462,14 +462,48 @@ class ExpositionDeleteForm(forms.ModelForm):
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)
area = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False)
class Meta:
model = Statistic
exclude = ('exposition')
class StatisticForm(forms.Form):
year = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), label='Год')
visitors = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False, label='Посетители')
members = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False, label='Участники')
area = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False, label='Площадь')
countries_number = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:70px'}), required=False, label='Число стран')
def __init__(self, *args, **kwargs):
"""
create dynamical translated fields fields
"""
super(StatisticForm, self).__init__(*args, **kwargs)
#creates translated forms example: name_ru, name_en
# len(10) is a hack for detect if settings.LANGUAGES is not configured it return all langs
if len(settings.LANGUAGES) in range(10):
for lid, (code, name) in enumerate(settings.LANGUAGES):
# uses enumerate for detect iteration number
# first iteration is a default lang so it required fields
required = True if lid == 0 else False
self.fields['countries_%s' % code] = forms.CharField(label=u'Участвующие страны',
required=False,
widget=forms.TextInput(attrs={'style':'width: 250px'}))
def save(self, exposition=None):
data = self.cleaned_data
if not exposition:
return None
else:
stat = Statistic()
# simple fields
stat.exposition = exposition
stat.year = data['year']
stat.visitors = data.get('visitors')
stat.members = data.get('members')
stat.area = data.get('area')
stat.countries_number = data.get('countries_number')
fill_with_signal(Statistic, stat, data)
return stat
def clean_year(self):
cleaned_data = super(StatisticForm, self).clean()
@ -486,6 +520,11 @@ class StatisticForm(forms.ModelForm):
visitors = cleaned_data.get('visitors').strip()
return is_positive_integer(visitors)
def clean_countries_number(self):
cleaned_data = super(StatisticForm, self).clean()
countries_number = cleaned_data.get('countries_number').strip()
return is_positive_integer(countries_number)
from functions.files import check_tmp_timetables
class TimeTableForm(forms.Form):

@ -0,0 +1,201 @@
# -*- coding: utf-8 -*-
import os
import MySQLdb
from MySQLdb.cursors import DictCursor
from django.core.management.base import BaseCommand
from django.conf import settings
from exposition.models import Exposition
from conference.management.commands.conf_old import filter_city, filter_country, get_periodic, get_logo, get_places
from django.core.files import File
from functions.translate import fill_with_signal
from country.models import Country
from city.models import City
file_path = settings.MEDIA_ROOT + 'exposition/bad_expos.txt'
import datetime
from theme.models import Theme
from conference.models import Conference
'''
class Command(BaseCommand):
def handle(self, *args, **options):
db = MySQLdb.connect(host="localhost",
user="expomap",
passwd="7FbLtAGjse",
db="old_db",
charset='utf8',
cursorclass=DictCursor)
cursor = db.cursor()
conf_old = """
SELECT DISTINCT (products_to_categories.products_id), url as old_url
FROM `products_to_categories`
LEFT JOIN `products` ON products_to_categories.products_id=products.products_id
LEFT JOIN `products_description` ON products_to_categories.products_id=products_description.products_id
WHERE `products_status` =1
AND `conference` =0
"""
find_themes = "SELECT categories_id FROM `products_to_categories` WHERE `products_id` =%d"
cursor.execute(conf_old)
conferences = cursor.fetchall()
#for item in conferences:
cursor.execute(find_themes%conferences[0]['products_id'])
day = datetime.date.today()
day = day.replace(month=1, day=1)
for item in conferences:
old_url = item['old_url']
if not old_url:
continue
try:
expo = Exposition.objects.get(old_url=old_url)
except:
continue
if expo.data_begin > day:
continue
cursor.execute(find_themes%item['products_id'])
themes_id = [i['categories_id'] for i in cursor.fetchall()]
theme_qs = Theme.objects.filter(id__in=themes_id)
expo.theme.add(*theme_qs)
print(expo)
# if item['categories_id'] == 0:
# continue
# Theme.objects.get(id=item['categories_id'])
#print(result)
'''
from haystack.query import SearchQuerySet
from django.db import IntegrityError
from django.utils import translation
class Command(BaseCommand):
def handle(self, *args, **options):
db = MySQLdb.connect(host="localhost",
user="expomap",
passwd="7FbLtAGjse",
db="old_db",
charset='utf8',
cursorclass=DictCursor)
cursor = db.cursor()
sql = """
SELECT products.products_id as id, products_date_added as created, products_last_modified as modified,
discount, expohit, ufi, products_name as name, products_description as description,
products_short_description as main_title, products_viewed as viewed, products_period as period,
products_org as organiser,products_products as products, products_official as web_page,
products_img1 as logo, products_startdate as data_begin, products_enddate as data_end,
url as old_url, places_id
FROM `products`
LEFT JOIN `products_description` ON products.products_id=products_description.products_id
WHERE `products_status` =1
AND `conference` =0 AND places_id >0
ORDER BY products.products_id DESC
"""
translation.activate('ru')
expos = list(Exposition.objects.language().filter(old_url=''))
find_expo = "SELECT products_name, url from products_description WHERE products_name = '%s'"
for expo in expos:
cursor.execute(find_expo%expo.name)
result = cursor.fetchall()
if result:
expo.old_url = result[0]['url']
expo.save()
print(expo)
#cursor.execute(sql)
#result = cursor.fetchall()
#names = [item['name'] for item in result]
#media = settings.MEDIA_ROOT.replace('media/', '')
#counter = 0
#bad_cities = {}
bad_expos = []
'''
for i, item in enumerate(result):
qs = SearchQuerySet().models(Exposition).filter(name_ru=item['name'])
if not item:
continue
if not qs.count()>0:
continue
expo =qs[0].object
if not expo or expo.old_url:
continue
print(expo)
expo.old_url = item['old_url']
try:
expo.save()
except IntegrityError:
continue
"""
print('number: %d, errors: %d'%(i, len(bad_expos)))
name = item['name']
if Exposition.objects.filter(translations__name=name).exists():
msg = u'%s|||%s|||%s'%(name, item['old_url'], 'already exist')
bad_expos.append(msg)
continue
data_begin = item['data_begin']
data_end= item['data_end']
place_id = item['places_id'] # convert to country and city
country, city = get_places(place_id)
if not country or not city:
msg = u'%s|||%s|||%s'%(name, item['old_url'], 'bad country or city')
bad_expos.append(msg)
continue
old_url = item['old_url']
periodic = item['period']
periodic = get_periodic(periodic)
web_page = item['web_page']
currency = 'USD'
expohit = item['expohit']
ufi = item['ufi']
if ufi:
ufi = 1
else:
ufi = 0
created = item['created']
modified = item['modified']
data = {'name_ru': name, 'main_title_ru': item['main_title'], 'description_ru': item['description'],
'products_ru': item['products'], 'discount_description_ru': '', 'time_ru': '', 'price_day_ru':'',
'price_all_ru': '', 'price_day_bar_ru': '', 'price_all_bar_ru': '', 'stat_countries_ru': '',
'pre_condition_ru':'', 'stand_condition_ru': '', 'visit_note_ru': '', 'participation_note_ru': '',
'title_ru': '', 'descriptions_ru': '', 'keywords_ru': ''}
exposition = Exposition(data_begin=data_begin, data_end=data_end, city=city, country=country,
web_page=web_page, old_url=old_url, periodic=periodic, currency=currency,
expohit=expohit, created=created, modified=modified, quality_label=ufi)
try:
fill_with_signal(Exposition, exposition, data)
except Exception as e:
msg = u'%s|||%s|||%s'%(name, item['old_url'], str(e))
bad_expos.append(msg)
continue
"""
'''

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
import xlrd
from django.core.management.base import BaseCommand
from django.conf import settings
from functions.form_check import translit_with_separator
from exposition.models import Exposition
from organiser.models import Organiser
CHINA_FILE = settings.MEDIA_ROOT+'/import/expo_china_ru.xlsx'
GERMANY_FILE = settings.MEDIA_ROOT+'/import/expo_germany_ru.xlsx'
# 391 row not imported(same url)
ITALY_FILE = settings.MEDIA_ROOT+'/import/expo_italy_ru.xlsx'
# moscow 3 exps
F = settings.MEDIA_ROOT+'/import/exp.xlsx'
LA_FILE = settings.MEDIA_ROOT+'/import/expo_la.xlsx'
NA_EU_ASIA_FILE = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa.xls'
NA_EU_ASIA_FILE2 = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa_part2.xls'
RUSSIA_FILE = settings.MEDIA_ROOT+'/import/expo_russia.xls'
class Command(BaseCommand):
def handle(self, *args, **options):
f = open(RUSSIA_FILE, 'r')
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)]
labels = [label for label in row_list[0]]
for row_number, row in enumerate(row_list[1:]):
exp_url = translit_with_separator(row[2])
try:
exp = Exposition.objects.get(url=exp_url)
except Exposition.DoesNotExist:
continue
cell1 = row[11].split(';')
cell2 = row[12].split(';')
orgs = [item.strip() for item in cell1+cell2 if item]
exp.organiser.clear()
for org in orgs:
url = translit_with_separator(org)
try:
organiser = Organiser.objects.get(url=url)
except Organiser.DoesNotExist:
organiser = Organiser(url=url)
organiser.translate('ru')
organiser.name = org
organiser.save()
except Organiser.MultipleObjectsReturned:
continue
if not exp.organiser.filter(url=organiser.url).exists():
exp.organiser.add(organiser)
print(exp)

@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
import xlrd
import urllib2
from django.core.management.base import BaseCommand
from django.conf import settings
from functions.form_check import translit_with_separator
from functions.files import get_alternative_filename
from exposition.models import Exposition, Statistic
from organiser.models import Organiser
CHINA_FILE = settings.MEDIA_ROOT+'/import/expo_china_ru.xlsx'
GERMANY_FILE = settings.MEDIA_ROOT+'/import/expo_germany_ru.xlsx'
# 391 row not imported(same url)
ITALY_FILE = settings.MEDIA_ROOT+'/import/expo_italy_ru.xlsx'
# moscow 3 exps
F = settings.MEDIA_ROOT+'/import/exp.xlsx'
LA_FILE = settings.MEDIA_ROOT+'/import/expo_la.xlsx'
NA_EU_ASIA_FILE = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa.xls'
NA_EU_ASIA_FILE2 = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa_part2.xls'
# 44
class Command(BaseCommand):
def handle(self, *args, **options):
qs = Statistic.objects.language('ru').exclude(translations__countries='')
comas = 0
enters = 0
main = 0
spaces = 0
word = 0
number = 0
for i in qs:
if ';' in i.countries:
main +=1
a = i.countries.split(';')
new = [item.strip() for item in a]
st = ';'.join(new)
#print st.encode('utf8')
i.countries = st
#i.save()
elif ',' in i.countries:
comas += 1
elif '\n' in i.countries:
enters += 1
elif ' ' in i.countries:
spaces += 1
print(i.countries.encode('utf8'))
if '55' in i.countries:
continue
elif '.' in i.countries:
number += 1
#print(i.countries)
#a = i.countries.split('.')
#i.countries_number = int(a[0])
#i.countries = ''
#i.save()
else:
word += 1
#print(i.countries.encode('utf8'))
print('all: %d'%qs.count())
print('main: %d'%main)
print('comas: %d'%comas)
print('enter: %d'%enters)
print('spaces: %d'%spaces)
print('word: %d'%word)
print('number: %d'%number)

@ -4,6 +4,8 @@ from django.core.management.base import BaseCommand
from django.conf import settings
from exposition.models import Exposition
from import_xls.excel_settings import event_sett
from django.db import IntegrityError
from django.utils import translation
CHINA_FILE = settings.MEDIA_ROOT+'/import/expo_china_ru.xlsx'
GERMANY_FILE = settings.MEDIA_ROOT+'/import/expo_germany_ru.xlsx'
@ -14,35 +16,57 @@ F = settings.MEDIA_ROOT+'/import/exp.xlsx'
LA_FILE = settings.MEDIA_ROOT+'/import/expo_la.xlsx'
NA_EU_ASIA_FILE = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa.xls'
NA_EU_ASIA_FILE2 = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa_part2.xls'
RUSSIA_FILE = settings.MEDIA_ROOT+'/import/expo_russia.xls'
GEORGIA_FILE = settings.MEDIA_ROOT+'/import/georgia.xls'
class Command(BaseCommand):
def handle(self, *args, **options):
f = open(NA_EU_ASIA_FILE, 'r')
f = open(GEORGIA_FILE, 'r')
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)]
labels = [label for label in row_list[0]]
existing = 0
for row_number, row in enumerate(row_list[1:]):
print(row_number)
#print(row_number)
name = row[2]
if row[0] != '':
# in first column ids
try:
object = Exposition.objects.language('ru').get(id=int(row[0]))
existing += 1
except ValueError:
object = Exposition()
object.translate('ru')
except Exposition.DoesNotExist:
object = Exposition(id= int(row[0]))
object.translate('ru')
existing += 1
else:
# if id blank - its a new place
object = Exposition()
object.translate('ru')
"""
try:
object = Exposition.objects.language('ru').filter(translations__name=name)[0]
existing += 1
except IndexError:
pass
"""
methods = []
for col_number, cell in enumerate(row):
label = labels[col_number]
@ -76,11 +100,16 @@ class Command(BaseCommand):
pass
else:
setattr(object, field_name, value)
#object.save()
try:
object.save()
except IntegrityError:
continue
print('post save %s'% str(object))
"""
for method in methods:
func = method['func']
if method.get('purpose'):
@ -90,4 +119,5 @@ class Command(BaseCommand):
continue
else:
func(object, method['value'])
"""
print(existing)

@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
import xlrd
import urllib2
from django.core.management.base import BaseCommand
from django.conf import settings
from functions.form_check import translit_with_separator
from functions.files import get_alternative_filename
from exposition.models import Exposition
from organiser.models import Organiser
CHINA_FILE = settings.MEDIA_ROOT+'/import/expo_china_ru.xlsx'
GERMANY_FILE = settings.MEDIA_ROOT+'/import/expo_germany_ru.xlsx'
# 391 row not imported(same url)
ITALY_FILE = settings.MEDIA_ROOT+'/import/expo_italy_ru.xlsx'
# moscow 3 exps
F = settings.MEDIA_ROOT+'/import/exp.xlsx'
LA_FILE = settings.MEDIA_ROOT+'/import/expo_la.xlsx'
NA_EU_ASIA_FILE = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa.xls'
NA_EU_ASIA_FILE2 = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa_part2.xls'
class Command(BaseCommand):
def handle(self, *args, **options):
f = open(CHINA_FILE, 'r')
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)]
labels = [label for label in row_list[0]]
for row_number, row in enumerate(row_list[1:]):
exp_url = translit_with_separator(row[2])
try:
exp = Exposition.objects.get(url=exp_url)
except Exposition.DoesNotExist:
continue
if exp.logo or row[19] == '':# or row[16].startswith('http') or row[16].startswith('https') or not row[16].startswith('/') or row[16].startswith('../'):
continue
path = row[19]
file_name = path.split('/')[-1]
logo_path = exp.logo.field.upload_to
full_path = settings.MEDIA_ROOT + logo_path
try:
alt_name = get_alternative_filename(full_path, file_name)
except UnicodeEncodeError:
continue
download_to = full_path+alt_name
if path.startswith('http') or path.startswith('https'):
url = path
elif path.startswith('/'):
url = 'http://expomap.ru' + path
elif path.startswith('images'):
url = 'http://expomap.ru/' + path
else:
continue
#print('------------------------------------')
#print(path)
#print(url)
#print('------------------------------------')
try:
response = urllib2.urlopen(url, timeout=15)
except:
continue
if response.code != 200:
continue
with open(download_to,'wb') as f:
try:
f.write(response.read())
f.close()
except:
# can be timeout
continue
exp.logo = logo_path + alt_name
try:
exp.save()
print(exp)
except:
print('logo exception. logo: %s'%exp.logo)
continue

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
import xlrd
import urllib2
from django.core.management.base import BaseCommand
from django.conf import settings
from functions.form_check import translit_with_separator
from functions.files import get_alternative_filename
from exposition.models import Exposition, Statistic
from organiser.models import Organiser
CHINA_FILE = settings.MEDIA_ROOT+'/import/expo_china_ru.xlsx'
GERMANY_FILE = settings.MEDIA_ROOT+'/import/expo_germany_ru.xlsx'
# 391 row not imported(same url)
ITALY_FILE = settings.MEDIA_ROOT+'/import/expo_italy_ru.xlsx'
# moscow 3 exps
F = settings.MEDIA_ROOT+'/import/exp.xlsx'
LA_FILE = settings.MEDIA_ROOT+'/import/expo_la.xlsx'
NA_EU_ASIA_FILE = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa.xls'
NA_EU_ASIA_FILE2 = settings.MEDIA_ROOT+'/import/expo_na_eu_ sa_part2.xls'
RUSSIA_FILE = settings.MEDIA_ROOT+'/import/expo_russia.xls'
class Command(BaseCommand):
def handle(self, *args, **options):
f = open(RUSSIA_FILE, 'r')
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)]
labels = [label for label in row_list[0]]
for row_number, row in enumerate(row_list[1:]):
exp_url = translit_with_separator(row[2])
try:
exp = Exposition.objects.language('ru').get(url=exp_url)
except Exposition.DoesNotExist:
continue
if not row[30]:
continue
year = int(row[30])
try:
countries_number = int(exp.stat_countries)
countries = ''
except ValueError:
countries_number = None
countries = exp.stat_countries
members = exp.members
visitors = exp.visitors
area = exp.area
s = Statistic(exposition=exp,
year=year,
countries_number=countries_number,
members=members,
visitors=visitors,
area=area)
s.translate('ru')
s.countries = countries
s.save()
print(exp)

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from django.core.management.base import BaseCommand
from meta.models import MetaSetting
class Command(BaseCommand):
def handle(self, *args, **options):
a = MetaSetting.objects.filter(translations__h1__contains='«').count()
qs = MetaSetting.objects.language('ru').all()
for item in qs:
item.title = item.title.replace(u'«', u'').replace(u'»', u'')
item.description = item.title.replace(u'«', u'').replace(u'»', u'')
item.h1 = item.h1.replace(u'«', u'').replace(u'»', u'')
#item.save()

@ -5,9 +5,10 @@ from hvad.models import TranslationManager
class ClientManager(TranslationManager):
def get_query_set(self):
now = datetime.datetime.now().date()
return super(ClientManager, self).get_query_set().filter(is_published=True, data_begin__gte=now).order_by('data_begin')
return self.language().select_related('country', 'city', 'place').filter(is_published=True).order_by('data_begin')
def upcoming(self):
return self.filter(data_begin__gte=datetime.datetime.now().date())
"""

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import copy, datetime
from django.db import models
from django.db.models import Q
from django.db.models.signals import post_save, pre_save
from django.utils.translation import ugettext as _
from django.utils import translation
@ -19,6 +20,8 @@ from functions.model_mixin import EventMixin, ExpoMixin
from functions.translate import fill_with_signal
from photologue.models import Gallery
from import_xls.model_utils import ExpoImportManager
from functions.models_methods import hvad_to_dict
AUDIENCE1 = ((None,_(u'Не выбрано')),
('experts', _(u'Специалисты')),
@ -28,14 +31,13 @@ AUDIENCE1 = ((None,_(u'Не выбрано')),
AUDIENCE = (None,'experts', 'experts and consumers', 'general public')
BIT_AUDIENCE = (('experts', _(u'Специалисты')), ('experts and consumers', _(u'Специалисты и потребители')),
('general public', _(u'Широкая публика')))
BIT_AUDIENCE = settings.BIT_AUDIENCE
CURRENCY = ('RUB', 'USD', 'EUR', 'RMB', 'GBP')
CURRENCY = settings.CURRENCY
# 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 = [item.url for item in Service.objects.all()] if db_table_exists('service_service') else []
class Exposition(TranslatableModel, EventMixin, ExpoMixin):
@ -52,6 +54,7 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin):
event_type = 'expo'
url = models.SlugField(unique=True, max_length=255)
old_url = models.SlugField(unique=True, max_length=255)
data_begin = models.DateField(verbose_name='Дата начала')
data_end = models.DateField(verbose_name='Дата окончания')
services = BitField(flags=flags)
@ -161,8 +164,19 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin):
def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk))
def get_services(self):
country_ids = [item for item, bool in self.country.services if bool==True]
ids = [item for item, bool in self.services if bool==True]
qs = Service.objects.language().filter(Q(Q(url__in=country_ids) & Q(type=Service.type.expo)) | Q(url__in=ids))
return list(qs)
def get_parent(self):
return {}
def get_absolute_url(self):
return self.get_permanent_url()
def get_index_text(self):
translation.activate('ru')
@ -231,7 +245,7 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin):
for k, v in BIT_AUDIENCE:
for item in checked:
if item == k:
audience.append(v)
audience.append(unicode(v))
return ', '.join(audience)
@ -246,7 +260,7 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin):
if self.theme.all():
theme = self.theme.all()[0]
now = datetime.datetime.now()
now = now.replace(day=now.day-1)
now = now - datetime.timedelta(days=1)
expositions = Exposition.objects.filter(theme__in=[theme], data_begin__gt=now).exclude(id=self.id).order_by('data_begin')
return expositions[:3]
else:
@ -284,58 +298,22 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin):
return code
return cur
def clone(self):
"""
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
# url must be unique
duplicate.url += '_copy'
if Exposition.objects.safe_get(url=duplicate.url):
#already has copy this instance
return
# duplicate should not be published
duplicate.is_published = 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()
# but lost all ManyToMany relations and Translations.
# copy relations
for field in self._meta.many_to_many:
source = getattr(self, field.attname)
destination = getattr(duplicate, field.attname)
for item in source.all():
destination.add(item)
return duplicate
class Statistic(models.Model):
class Statistic(TranslatableModel):
exposition = models.ForeignKey(Exposition, related_name='statistic')
year = models.PositiveIntegerField(verbose_name='Год')
members = models.PositiveIntegerField(verbose_name='Посетители')
visitors = models.PositiveIntegerField(verbose_name='Участники')
area = models.PositiveIntegerField(verbose_name='Площадь')
members = models.PositiveIntegerField(verbose_name='Посетители', blank=True, null=True)
visitors = models.PositiveIntegerField(verbose_name='Участники', blank=True, null=True)
area = models.PositiveIntegerField(verbose_name='Площадь', blank=True, null=True)
countries_number = models.PositiveIntegerField(verbose_name='Количество стран', blank=True, null=True)
translations = TranslatedFields(
countries = models.TextField(blank=True)
)
def to_dict(self):
return hvad_to_dict(self)
from django.core import serializers
from functions.models_methods import hvad_to_dict
class TimeTable(TranslatableModel):
"""
@ -379,34 +357,10 @@ class TmpTimeTable(TranslatableModel):
place = 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)
post_save.connect(post_save_handler, sender=TmpTimeTable)
post_save.connect(post_save_handler, sender=Statistic)

@ -48,4 +48,7 @@ class ExpositionIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin):
elif lang=='en':
return self.name_en
else:
return self.name_ru
return self.name_ru
def get_updated_field(self):
return 'modified'

@ -4,82 +4,80 @@ from views import ExpositionStatistic, ExpositionPrice,\
ExpositionProgramme, ExpositionSearchView, ExpositionByCountry, ExpositionByTheme, ExpositionByCity
from django.http import HttpResponse
from django.views.decorators.cache import cache_page
from views import ExpositionServiceView
from views import ExpoCountryCatalog, ExpoCityCatalog, ExpoThemeCatalog, ExpoTagCatalog, ExpoList, ExpoDetail,\
ExpoVisitors, ExpoMembers
urlpatterns = patterns('',
url(r'expo/add-note/(?P<slug>.*)/$', 'exposition.views.add_note'),
url(r'exposition-add-calendar/(?P<id>\d+)/$', 'exposition.views.exposition_add_calendar'),
url(r'exposition-visit/(?P<id>\d+)/$', 'exposition.views.exposition_visit'),
url(r'^expo/add-note/(?P<slug>.*)/$', 'exposition.views.add_note'),
url(r'^exposition-add-calendar/(?P<id>\d+)/$', 'exposition.views.exposition_add_calendar'),
url(r'^exposition-visit/(?P<id>\d+)/$', 'exposition.views.exposition_visit'),
# search
url(r'expo/search/', ExpositionSearchView.as_view()),
url(r'^expo/search/', ExpositionSearchView.as_view()),
# country catalog
url(r'expo/country/$', ExpositionByCountry.as_view()),
url(r'expo/country/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoCountryCatalog.as_view()),
url(r'expo/country/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoCountryCatalog.as_view()),
url(r'expo/country/(?P<slug>.*)/page/(?P<page>\d+)/$', ExpoCountryCatalog.as_view()),
url(r'expo/country/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoCountryCatalog.as_view()),
url(r'expo/country/(?P<slug>.*)/(?P<year>\d+)/$', ExpoCountryCatalog.as_view()),
url(r'expo/country/(?P<slug>.*)/$', ExpoCountryCatalog.as_view()),
url(r'^expo/country/$', ExpositionByCountry.as_view(), {'meta_id':54}),
url(r'^expo/country/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoCountryCatalog.as_view(), {'meta_id':7}),
url(r'^expo/country/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoCountryCatalog.as_view(), {'meta_id':6}),
url(r'^expo/country/(?P<slug>.*)/page/(?P<page>\d+)/$', ExpoCountryCatalog.as_view(), {'meta_id':5}),
url(r'^expo/country/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoCountryCatalog.as_view(), {'meta_id':7}),
url(r'^expo/country/(?P<slug>.*)/(?P<year>\d+)/$', ExpoCountryCatalog.as_view(), {'meta_id':6}),
url(r'^expo/country/(?P<slug>.*)/$', ExpoCountryCatalog.as_view(), {'meta_id':5}),
# city catalog
url(r'expo/city/$', ExpositionByCity.as_view()),
url(r'expo/city/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoCityCatalog.as_view()),
url(r'expo/city/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoCityCatalog.as_view()),
url(r'expo/city/(?P<slug>.*)/page/(?P<page>\d+)/$', ExpoCityCatalog.as_view()),
url(r'expo/city/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoCityCatalog.as_view()),
url(r'expo/city/(?P<slug>.*)/(?P<year>\d+)/$', ExpoCityCatalog.as_view()),
url(r'expo/city/(?P<slug>.*)/$', ExpoCityCatalog.as_view()),
url(r'^expo/city/$', ExpositionByCity.as_view(), {'meta_id':53}),
url(r'^expo/city/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoCityCatalog.as_view(), {'meta_id':10}),
url(r'^expo/city/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoCityCatalog.as_view(), {'meta_id':9}),
url(r'^expo/city/(?P<slug>.*)/page/(?P<page>\d+)/$', ExpoCityCatalog.as_view(), {'meta_id':8}),
url(r'^expo/city/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoCityCatalog.as_view(), {'meta_id':10}),
url(r'^expo/city/(?P<slug>.*)/(?P<year>\d+)/$', ExpoCityCatalog.as_view(), {'meta_id':9}),
url(r'^expo/city/(?P<slug>.*)/$', ExpoCityCatalog.as_view(), {'meta_id':8}),
# theme catalog
url(r'expo/theme/$', ExpositionByTheme.as_view()),
url(r'expo/theme/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view()),
url(r'expo/theme/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view()),
url(r'expo/theme/(?P<slug>.*)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view()),
url(r'expo/theme/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoThemeCatalog.as_view()),
url(r'expo/theme/(?P<slug>.*)/(?P<year>\d+)/$', ExpoThemeCatalog.as_view()),
url(r'expo/theme/(?P<slug>.*)/$', ExpoThemeCatalog.as_view()),
url(r'^expo/theme/$', ExpositionByTheme.as_view(), {'meta_id':55}),
url(r'^expo/theme/(?P<slug>.*)/country/(?P<country_slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':44}),
url(r'^expo/theme/(?P<slug>.*)/country/(?P<country_slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoThemeCatalog.as_view(), {'meta_id':44}),
url(r'^expo/theme/(?P<slug>.*)/country/(?P<country_slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':44}),
url(r'^expo/theme/(?P<slug>.*)/country/(?P<country_slug>.*)/(?P<year>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':44}),
url(r'^expo/theme/(?P<slug>.*)/country/(?P<country_slug>.*)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':44}),
url(r'^expo/theme/(?P<slug>.*)/country/(?P<country_slug>.*)/$', ExpoThemeCatalog.as_view(), {'meta_id':44}),
url(r'^expo/theme/(?P<slug>.*)/city/(?P<city_slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':42}),
url(r'^expo/theme/(?P<slug>.*)/city/(?P<city_slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoThemeCatalog.as_view(), {'meta_id':42}),
url(r'^expo/theme/(?P<slug>.*)/city/(?P<city_slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':42}),
url(r'^expo/theme/(?P<slug>.*)/city/(?P<city_slug>.*)/(?P<year>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':42}),
url(r'^expo/theme/(?P<slug>.*)/city/(?P<city_slug>.*)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':42}),
url(r'^expo/theme/(?P<slug>.*)/city/(?P<city_slug>.*)/$', ExpoThemeCatalog.as_view(), {'meta_id':42}),
url(r'^expo/theme/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':13}),
url(r'^expo/theme/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':12}),
url(r'^expo/theme/(?P<slug>.*)/page/(?P<page>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':11}),
url(r'^expo/theme/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoThemeCatalog.as_view(), {'meta_id':13}),
url(r'^expo/theme/(?P<slug>.*)/(?P<year>\d+)/$', ExpoThemeCatalog.as_view(), {'meta_id':12}),
url(r'^expo/theme/(?P<slug>.*)/$', ExpoThemeCatalog.as_view(), {'meta_id':11}),
# tag catalog
url(r'expo/tag/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoTagCatalog.as_view()),
url(r'expo/tag/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoTagCatalog.as_view()),
url(r'expo/tag/(?P<slug>.*)/page/(?P<page>\d+)/$', ExpoTagCatalog.as_view()),
url(r'expo/tag/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoTagCatalog.as_view()),
url(r'expo/tag/(?P<slug>.*)/(?P<year>\d+)/$', ExpoTagCatalog.as_view()),
url(r'expo/tag/(?P<slug>.*)/$', ExpoTagCatalog.as_view()),
url(r'^expo/tag/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoTagCatalog.as_view(), {'meta_id':17}),
url(r'^expo/tag/(?P<slug>.*)/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoTagCatalog.as_view(), {'meta_id':15}),
url(r'^expo/tag/(?P<slug>.*)/page/(?P<page>\d+)/$', ExpoTagCatalog.as_view(), {'meta_id':14}),
url(r'^expo/tag/(?P<slug>.*)/(?P<year>\d+)/(?P<month>.*)/$', ExpoTagCatalog.as_view(), {'meta_id':17}),
url(r'^expo/tag/(?P<slug>.*)/(?P<year>\d+)/$', ExpoTagCatalog.as_view(), {'meta_id':15}),
url(r'^expo/tag/(?P<slug>.*)/$', ExpoTagCatalog.as_view(), {'meta_id':14}),
# expo additional pages
url(r'expo/(?P<slug>.*)/statistic/$', ExpositionStatistic.as_view()),
url(r'expo/(?P<slug>.*)/price/$', ExpositionPrice.as_view()),
url(r'expo/(?P<slug>.*)/program/$', ExpositionProgramme.as_view()),
url(r'expo/(?P<slug>.*)/visitors/page/(?P<page>\d+)/$', ExpoVisitors.as_view()),
url(r'expo/(?P<slug>.*)/visitors/$', ExpoVisitors.as_view()),
url(r'expo/(?P<slug>.*)/members/page/(?P<page>\d+)/$', ExpoMembers.as_view()),
url(r'expo/(?P<slug>.*)/members/$', ExpoMembers.as_view()),
url(r'expo/(?P<slug>.*)/service/(?P<service_url>.*)/', ExpositionServiceView.as_view()),
url(r'^expo/(?P<slug>.*)/statistic/$', ExpositionStatistic.as_view(), {'meta_id':60}),
url(r'^expo/(?P<slug>.*)/price/$', ExpositionPrice.as_view(), {'meta_id':61}),
url(r'^expo/(?P<slug>.*)/program/$', ExpositionProgramme.as_view(), {'meta_id':62}),
url(r'^expo/(?P<slug>.*)/visitors/page/(?P<page>\d+)/$', ExpoVisitors.as_view(), {'meta_id':64}),
url(r'^expo/(?P<slug>.*)/visitors/$', ExpoVisitors.as_view(), {'meta_id':64}),
url(r'^expo/(?P<slug>.*)/members/page/(?P<page>\d+)/$', ExpoMembers.as_view(), {'meta_id':63}),
url(r'^expo/(?P<slug>.*)/members/$', ExpoMembers.as_view(), {'meta_id':63}),
url(r'^expo/(?P<slug>.*)/service/(?P<service_url>.*)/', ExpositionServiceView.as_view()),
# expo list
url(r'expo/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoList.as_view()),
url(r'expo/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoList.as_view()),
url(r'expo/(?P<year>\d+)/(?P<month>.*)/$', ExpoList.as_view()),
url(r'expo/(?P<year>\d+)/$', ExpoList.as_view()),
url(r'expo/page/(?P<page>\d+)/$', ExpoList.as_view()),
url(r'^expo/(?P<year>\d+)/(?P<month>.*)/page/(?P<page>\d+)/$', ExpoList.as_view(), {'meta_id':4}),
url(r'^expo/(?P<year>\d+)/page/(?P<page>\d+)/$', ExpoList.as_view(), {'meta_id':3}),
url(r'^expo/(?P<year>\d+)/(?P<month>.*)/$', ExpoList.as_view(), {'meta_id':4}),
url(r'^expo/(?P<year>\d+)/$', ExpoList.as_view(), {'meta_id':3}),
url(r'^expo/page/(?P<page>\d+)/$', ExpoList.as_view(), {'meta_id':2}),
# expo page
url(r'expo/(?P<slug>.*)/$', ExpoDetail.as_view()),# event
url(r'expo/$', ExpoList.as_view()),
#url(r'expo/(?P<slug>.*)/service/(?P<url>.*)/$', ExpositionServiceView.as_view()),
#url(r'expo/(?P<params>.*)/service/(?P<url>.*)/$', ExpositionServiceView.as_view()),
#url(r'expo/(?P<params>.*)/statistic/$', ExpositionStatistic.as_view()),
url(r'^expo/(?P<slug>.*)/$', ExpoDetail.as_view(), {'meta_id':18}),# event
url(r'^expo/$', ExpoList.as_view() , {'meta_id':2}),
)

@ -7,7 +7,7 @@ from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from django.views.generic import ListView, DetailView
from django.utils.translation import ugettext as _
from django.shortcuts import get_object_or_404
from django.shortcuts import get_object_or_404, render_to_response
from django.http import Http404
from django.utils import translation
#models
@ -19,18 +19,19 @@ from country.models import Country
from city.models import City
from theme.models import Theme, Tag
from note.models import Note
from functions.custom_views import ExpoSearchView
from service.order_forms import AdvertiseForm
from functions.search_forms import ExpositionSearchForm
from functions.custom_views import ExpoSearchView
from meta.views import MetadataMixin
from functions.cache_mixin import JitterCacheMixin, CacheMixin
class ExpositionBy(ListView):
class ExpositionBy(JitterCacheMixin, MetadataMixin, ListView):
template_name = 'exposition/exposition_by.html'
title1 = ''
title2 = ''
"""
abstact class
"""
@ -42,47 +43,54 @@ class ExpositionBy(ListView):
class ExpositionByCountry(ExpositionBy):
cache_range = settings.CACHE_RANGE
model = Country
title1 = _(u'По странам')
title2 = _(u'Выставки мира по странам')
catalog = 'country/'
def get_queryset(self):
lang = translation.get_language()
return self.model.objects.select_related('exposition_country')\
.filter(exposition_country__country__isnull=False, translations__language_code=lang)\
.order_by('translations__name').distinct()
return self.model.objects.expo_countries_with_count()
#lang = translation.get_language()
#return self.model.objects.select_related('exposition_country')\
# .filter(exposition_country__country__isnull=False, translations__language_code=lang)\
# .order_by('translations__name').distinct()
class ExpositionByTheme(ExpositionBy):
cache_range = settings.CACHE_RANGE
model = Theme
title1 = _(u'По тематикам')
title2 = _(u'Выставки мира по тематикам')
catalog = 'theme/'
def get_queryset(self):
lang = translation.get_language()
return self.model.objects.select_related('exposition_themes')\
.filter(exposition_themes__theme__isnull=False, translations__language_code=lang)\
.order_by('translations__name').distinct()
return self.model.active.expo_themes_with_count()
#lang = translation.get_language()
#return self.model.objects.select_related('exposition_themes')\
# .filter(exposition_themes__theme__isnull=False, translations__language_code=lang)\
# .order_by('translations__name').distinct()
class ExpositionByCity(ExpositionBy):
cache_range = settings.CACHE_RANGE
model = City
title1 = _(u'По городам')
title2 = _(u'Выставки мира по городам')
catalog = 'city/'
def get_queryset(self):
lang = translation.get_language()
return self.model.objects.select_related('exposition_city')\
.filter(exposition_city__city__isnull=False, translations__language_code=lang)\
.order_by('translations__name').distinct()
return self.model.used.expo_cities_with_count()
#return self.model.used.expo_cities()
#lang = translation.get_language()
#return self.model.objects.select_related('exposition_city')\
# .filter(exposition_city__city__isnull=False, translations__language_code=lang)\
# .order_by('translations__name').distinct()
class ExpositionSearchView(ExpoSearchView):
#paginate_by = 10
template_name = 'exposition/search.html'
template_name = 'client/exposition/search.html'
search_form = ExpositionSearchForm
model = Exposition
@ -119,12 +127,6 @@ def exposition_visit(request, id):
args['in'] = True
args['success'] = True
"""
if exp:
exp.users.add(user)
args['success'] = True
"""
else:
args['not_authorized'] = True
args['success'] = True
@ -133,34 +135,48 @@ def exposition_visit(request, id):
#------------------------------------------------------------------------------
class ExpoDetail(DetailView):
class ExpoDetail(JitterCacheMixin, MetadataMixin, DetailView):
cache_range = settings.CACHE_RANGE
model = Exposition
slug_field = 'url'
template_name = 'client/exposition/exposition_detail.html'
class ExpositionProgramme(DetailView):
def get_context_data(self, **kwargs):
context = super(ExpoDetail, self).get_context_data(**kwargs)
context['advertising_form'] = AdvertiseForm()
return context
class ExpositionProgramme(MetadataMixin, DetailView):
model = Exposition
slug_field = 'url'
template_name = 'client/exposition/programm.html'
class ExpositionPrice(DetailView):
class ExpositionPrice(MetadataMixin, DetailView):
model = Exposition
slug_field = 'url'
template_name = 'client/exposition/price.html'
class ExpositionStatistic(DetailView):
class ExpositionStatistic(MetadataMixin, DetailView):
model = Exposition
slug_field = 'url'
template_name = 'client/exposition/statistic.html'
from django.views.generic.edit import FormMixin, ModelFormMixin
class ExpositionServiceView(FormMixin, DetailView):
class ExpositionServiceView(MetadataMixin, FormMixin, DetailView):
model = Exposition
slug_field = 'url'
service = None
success_url = '/service/thanks/'
def dispatch(self, request, *args, **kwargs):
service_url = self.kwargs.get('service_url')
service = get_object_or_404(Service, url=service_url)
self.service = service
self.template_name = service.template
return super(ExpositionServiceView, self).dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
@ -176,17 +192,16 @@ class ExpositionServiceView(FormMixin, DetailView):
return self.form_invalid(form)
def get_context_data(self, **kwargs):
kwargs.update({'meta_id': getattr(self.service, 'meta_id','')})
context = super(ExpositionServiceView, self).get_context_data(**kwargs)
service_url = self.kwargs.get('service_url')
service = get_object_or_404(Service, url=service_url)
self.service = service
self.template_name = service.template
form = order_forms.get(service_url)
self.form_class = form
if not form:
raise Http404
context['form'] = self.get_form(self.form_class)
context['service'] = service
context['service'] = self.service
context['object'] = self.get_object()
return context
@ -195,7 +210,7 @@ class ExpositionServiceView(FormMixin, DetailView):
order.exposition = self.object
order.save()
messages.success(self.request, _(u'Ваш запрос был успешно отправлен'))
return HttpResponseRedirect(self.request.path)
return HttpResponseRedirect(self.success_url)
def get_initial(self):
"""
@ -217,7 +232,8 @@ class ExpositionServiceView(FormMixin, DetailView):
return self.initial.copy()
class ExpoList(ListView):
class ExpoList(MetadataMixin, JitterCacheMixin, ListView):
cache_range = settings.CACHE_RANGE
model = Exposition
paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/exposition/exposition_list.html'
@ -228,15 +244,12 @@ class ExpoList(ListView):
def get_queryset(self):
if self.request.user.is_staff:
now = datetime.datetime.now().date()
qs = self.model.objects.filter(data_begin__gte=now).order_by('data_begin')
qs = self.model.objects.upcoming()
else:
qs = self.model.enable.all()
qs = self.model.enable.upcoming()
year = self.kwargs.get('year')
if year:
qs = qs.filter(data_begin__year=year)
qs = self.model.enable.filter(data_end__year=year)
# info for breadscrumbs
self.year = {'text': year, 'link': '%s%s/'%(self.catalog_url, year)}
@ -255,14 +268,9 @@ class ExpoList(ListView):
context['month'] = self.month
return context
MONTHES = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2, 'name': _(u'Февраль')},
'mar': {'value': 3, 'name': _(u'Март')}, 'apr': {'value': 4, 'name': _(u'Апрель')},
'may': {'value': 5, 'name': _(u'Май')}, 'jun': {'value': 6, 'name': _(u'Июнь')},
'jul': {'value': 7, 'name': _(u'Июль')}, 'aug': {'value': 8, 'name': _(u'Август')},
'sep': {'value': 9, 'name': _(u'Сентябрь')}, 'oct': {'value': 10, 'name': _(u'Октябрь')},
'nov': {'value': 11, 'name': _(u'Ноябрь')}, 'dec': {'value': 12, 'name': _(u'Декабрь')}}
MONTHES = settings.MONTHES
class ExpoCatalog(ListView):
class ExpoCatalog(MetadataMixin, ListView):
model = Exposition
paginate_by = settings.CLIENT_PAGINATION
template_name = 'exposition/catalog.html'
@ -270,6 +278,8 @@ class ExpoCatalog(ListView):
filter_object = None
year = None
month = None
country = None
city = None
def get_filtered_qs(self):
# diferent for views
@ -280,11 +290,24 @@ class ExpoCatalog(ListView):
year = self.kwargs.get('year')
if year:
qs = qs.filter(data_begin__year=year)
qs = self.model.enable.filter(data_end__year=year)
filter_object = self.filter_object
if isinstance(filter_object, Country):
qs = qs.filter(country=filter_object)
elif isinstance(filter_object, City):
qs = qs.filter(city=filter_object)
elif isinstance(filter_object, Theme):
qs = qs.filter(theme=filter_object)
if self.kwargs.get('country'):
qs = qs.filter(country=self.kwargs.get('country'))
if self.kwargs.get('city'):
qs = qs.filter(city=self.kwargs.get('city'))
elif isinstance(filter_object, Tag):
qs = qs.filter(tag=filter_object)
# info for breadscrumbs
self.year = {'text': year, 'link': '%s%s/%s/'%(self.catalog_url, self.filter_object.url, year)}
month = self.kwargs.get('month')
monthes = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2, 'name': _(u'Февраль')},
'mar': {'value': 3, 'name': _(u'Март')}, 'apr': {'value': 4, 'name': _(u'Апрель')},
@ -294,7 +317,14 @@ class ExpoCatalog(ListView):
'nov': {'value': 11, 'name': _(u'Ноябрь')}, 'dec': {'value': 12, 'name': _(u'Декабрь')}}
if month and monthes.get(month):
qs = qs.filter(data_begin__month=monthes[month]['value'])
self.month = {'text': monthes[month]['name'], 'link': '%s%s/%s/%s/'%(self.catalog_url, self.filter_object.url, year, month)}
if self.country:
self.month = {'text': monthes[month]['name'], 'link': '%s%s/country/%s/%s/%s/'%
(self.catalog_url, self.filter_object.url, self.country.url, year, month)}
elif self.city:
self.month = {'text': monthes[month]['name'], 'link': '%s%s/city/%s/%s/%s/'%
(self.catalog_url, self.filter_object.url, self.city.url, year, month)}
else:
self.month = {'text': monthes[month]['name'], 'link': '%s%s/%s/%s/'%(self.catalog_url, self.filter_object.url, year, month)}
return qs.order_by('data_begin')
@ -314,8 +344,9 @@ class ExpoCountryCatalog(ExpoCatalog):
#this method used in parent get_queryset
slug = self.kwargs.get('slug')
country = get_object_or_404(Country, url=slug)
self.kwargs['country'] = country
self.filter_object = country
qs = self.model.enable.filter(country=country)
qs = self.model.enable.upcoming().filter(country=country)
return qs
class ExpoCityCatalog(ExpoCatalog):
@ -324,21 +355,51 @@ class ExpoCityCatalog(ExpoCatalog):
#this method used in parent get_queryset
slug = self.kwargs.get('slug')
city = get_object_or_404(City, url=slug)
qs = self.model.enable.filter(city=city)
self.kwargs['city'] = city
qs = self.model.enable.upcoming().filter(city=city)
self.filter_object = city
return qs
class ExpoThemeCatalog(ExpoCatalog):
template_name = 'exposition/catalog_theme.html'
catalog_url = '/expo/theme/'
country = None
city = None
def get_filtered_qs(self):
#this method used in parent get_queryset
slug = self.kwargs.get('slug')
country_slug = self.kwargs.get('country_slug')
city_slug = self.kwargs.get('city_slug')
theme = get_object_or_404(Theme, url=slug)
qs = self.model.enable.filter(theme=theme)
self.kwargs['theme'] = theme
qs = self.model.enable.upcoming().filter(theme=theme)
if country_slug:
country = get_object_or_404(Country, url=country_slug)
self.country = country
self.kwargs['country'] = country
qs = qs.filter(country=country)
if city_slug:
city = get_object_or_404(City, url=city_slug)
self.city = city
self.kwargs['city'] = city
qs = qs.filter(city=city)
self.filter_object = theme
return qs
def get_context_data(self, **kwargs):
context = super(ExpoThemeCatalog, self).get_context_data(**kwargs)
if self.country:
context['country'] = self.country
if self.city:
context['city'] = self.city
context['theme_for_filter'] = self.kwargs['theme']
return context
class ExpoTagCatalog(ExpoCatalog):
catalog_url = '/expo/tag/'
@ -346,12 +407,13 @@ class ExpoTagCatalog(ExpoCatalog):
#this method used in parent get_queryset
slug = self.kwargs.get('slug')
tag = get_object_or_404(Tag, url=slug)
qs = self.model.enable.filter(tag=tag)
self.kwargs['tag'] = tag
qs = self.model.enable.upcoming().filter(tag=tag)
self.filter_object = tag
return qs
class ExpoVisitors(ListView):
class ExpoVisitors(MetadataMixin, ListView):
paginate_by = settings.CLIENT_PAGINATION
model = Exposition
#template_name = 'event_visitors.html'
@ -365,6 +427,7 @@ class ExpoVisitors(ListView):
slug = self.kwargs.get('slug')
exposition = get_object_or_404(self.model, url=slug)
self.obj = exposition
self.object = self.obj
return exposition.users.all()
def get_context_data(self, **kwargs):
@ -374,7 +437,7 @@ class ExpoVisitors(ListView):
return context
class ExpoMembers(ListView):
class ExpoMembers(MetadataMixin, ListView):
paginate_by = settings.CLIENT_PAGINATION
model = Exposition
#template_name = 'event_visitors.html'
@ -388,6 +451,7 @@ class ExpoMembers(ListView):
slug = self.kwargs.get('slug')
exposition = get_object_or_404(self.model, url=slug)
self.obj = exposition
self.object = self.obj
return exposition.company.all()
def get_context_data(self, **kwargs):

@ -17,8 +17,8 @@ import pytils, re
class FileForm(forms.Form):
file_path = forms.FileField(label='Выберите файл')
model = forms.CharField(required=False, widget=forms.HiddenInput())
purposes = [('scheme teritory','Схема територии'),('preview','Превью')]
purpose = forms.ChoiceField(label='Назаначение', choices=purposes)
purposes = [('scheme teritory','Схема территории'),('preview','Превью'), ('preview2','Превью2')]
purpose = forms.ChoiceField(label='Назначение', choices=purposes)
def __init__(self, *args, **kwargs):
"""

@ -20,7 +20,8 @@ PURPOSES = (('photo', 'Фото'),
('map','Карта'),
('scheme teritory','Схема територии'),
('diplom','Дипломы'),
('preview','Превью')
('preview','Превью'),
('preview2','Превью'),
)
class FileModel(TranslatableModel):

@ -44,6 +44,6 @@ class AdminFilterForm(forms.Form):
qs = model.objects.all()
if name:
qs = qs.filter(translations__name__contains=name).distinct()
qs = qs.filter(translations__name__icontains=name).distinct()
return qs

@ -25,6 +25,11 @@ class AdminView(FormView):
obj = get_object_or_404(self.model, slug=slug)
self.obj = obj
return obj
id = self.kwargs.get('id')
if id:
obj = get_object_or_404(self.model, id=id)
self.obj = obj
return obj
self.obj = None
return None

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
import random
from django.contrib.auth.decorators import login_required
from django.utils.cache import patch_response_headers
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page, never_cache
from django.views.decorators.csrf import csrf_exempt
class NeverCacheMixin(object):
@method_decorator(never_cache)
def dispatch(self, *args, **kwargs):
return super(NeverCacheMixin, self).dispatch(*args, **kwargs)
class LoginRequiredMixin(object):
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
class CacheMixin(object):
cache_timeout = 60
def get_cache_timeout(self):
return self.cache_timeout
def dispatch(self, *args, **kwargs):
return cache_page(self.get_cache_timeout())(super(CacheMixin, self).dispatch)(*args, **kwargs)
class CacheControlMixin(object):
cache_timeout = 60
def get_cache_timeout(self):
return self.cache_timeout
def dispatch(self, *args, **kwargs):
response = super(CacheControlMixin, self).dispatch(*args, **kwargs)
patch_response_headers(response, self.get_cache_timeout())
return response
class JitterCacheMixin(CacheControlMixin):
cache_range = [60, 120]
def get_cache_range(self):
return self.cache_range
def get_cache_timeout(self):
return random.randint(*self.get_cache_range())

@ -227,7 +227,7 @@ class ExpoListView(ExpoMixin, ListView):
"""
"""
paginate_by = 10
paginate_by = settings.CLIENT_PAGINATION
params = None
single_page = False
search_form = None
@ -320,17 +320,16 @@ class EventDetail(ExpoMixin, DetailView):
from haystack.query import EmptySearchQuerySet
class ExpoSearchView(ListView):
paginate_by = 10
paginate_by = settings.CLIENT_PAGINATION
template_name = None
search_form = None
model = None
def get_queryset(self):
def get_queryset(self):
if self.request.GET:
form = self.search_form(self.request.GET)
if form.is_valid():
return form.search()
else:
return EmptySearchQuerySet()
@ -340,10 +339,13 @@ class ExpoSearchView(ListView):
def get_context_data(self, **kwargs):
context = super(ExpoSearchView, self).get_context_data(**kwargs)
form = self.search_form(self.request.GET)
if self.request.GET:
form = self.search_form(self.request.GET)
if form.is_valid():
form.data_with_parents = form.get_form_data()
else:
form = self.search_form()
context['search_form'] = form
@ -352,4 +354,5 @@ class ExpoSearchView(ListView):
del queries['page']
context['queries'] = queries
return context

@ -20,7 +20,7 @@ from slugify import slugify
def translit_with_separator(string, separator='-'):
return slugify(string, to_lower=True)
#return slugify(string)
"""
Trsanslit string and replace "bad" symbols for separator

@ -77,8 +77,9 @@ class EventMixin(object):
def get_services(self):
ids = [item for item, bool in self.country.services if bool==True]
##sasa
country_ids = [item for item, bool in self.country.services if bool==True]
ids = [item for item, bool in self.services if bool==True and item in country_ids]
return list(Service.objects.language().filter(url__in=ids).order_by('sort'))
def duration_days(self, month=None):

@ -1,7 +1,17 @@
import datetime
from django.utils.translation import get_language
from django.db.models import Q
from django.core.cache import cache
from django.utils import translation
from hvad.models import TranslationManager
class ExpoManager(TranslationManager):
def upcoming(self):
return self.language().select_related('country', 'city', 'place').filter(data_begin__gte=datetime.datetime.now().date()).order_by('data_begin')
def all(self, lang=None):
if lang:
return super(ExpoManager, self).language(lang).all().order_by('name')
@ -16,6 +26,110 @@ class ExpoManager(TranslationManager):
return None
class CityManager(TranslationManager):
cache_time = 600
def all(self):
lang = get_language()
qs = super(CityManager, self).select_related('exposition_city', 'conference_city')
qs = qs.filter(Q(exposition_city__city__isnull=False) | Q(conference_city__city__isnull=False))\
.order_by('translations__name').distinct()
return qs
def active_qs(self):
from exposition.models import Exposition
cities_id = [item['city_id'] for item in Exposition.objects.values('city_id').distinct()]
return self.language().filter(id__in=cities_id)
def expo_cities(self):
lang = translation.get_language()
key = 'used_expo_cities_%s'%lang
cached_cities = cache.get(key)
if cached_cities:
return cached_cities
else:
from exposition.models import Exposition
cities_id = [item['city_id'] for item in Exposition.objects.values('city_id').distinct()]
cities = list(self.language().filter(id__in=cities_id))
cache.set(key, cities, self.cache_time)
return cities
def expo_cities_with_count(self):
lang = translation.get_language()
key = 'used_expo_cities_count_%s'%lang
cached_cities = cache.get(key)
if cached_cities:
return cached_cities
else:
from exposition.models import Exposition
sql = {'expo_count':
"""SELECT COUNT(*)
FROM exposition_exposition
WHERE exposition_exposition.city_id = city_city.id
AND exposition_exposition.data_end >= CURDATE()
AND exposition_exposition.is_published = 1"""}
now = datetime.datetime.now().date()
# id of unique cities
cities_id = [item['city_id'] for item in Exposition.objects.filter(is_published=True, data_end__gte=now).values('city_id').distinct()]
cities = set(list(self.language().filter(id__in=cities_id).extra(select=sql)))
cities = sorted(cities, key=lambda x: x.name)
cache.set(key, cities, self.cache_time)
return cities
def conference_cities_with_count(self):
lang = translation.get_language()
key = 'used_conference_cities_count_%s'%lang
cached_cities = cache.get(key)
if cached_cities:
return cached_cities
else:
from conference.models import Conference
sql = {'conference_count':
"""SELECT COUNT(*)
FROM conference_conference
WHERE conference_conference.city_id = city_city.id
AND conference_conference.data_end >= CURDATE()
AND conference_conference.is_published = 1"""}
now = datetime.datetime.now().date()
# id of unique countries
cities_id = [item['city_id'] for item in Conference.objects.filter(is_published=True, data_end__gte=now).values('city_id').distinct()]
cities = set(list(self.language().filter(id__in=cities_id).extra(select=sql)))
cities = sorted(cities, key=lambda x: x.name)
cache.set(key, cities, self.cache_time)
return cities
def conference_cities(self):
lang = translation.get_language()
key = 'used_conference_cities_%s'%lang
cached_cities = cache.get(key)
if cached_cities:
return cached_cities
else:
from conference.models import Conference
cities_id = [item['city_id'] for item in Conference.objects.values('city_id').distinct()]
cities = list(self.language().filter(id__in=cities_id))
cache.set(key, cities, self.cache_time)
return cities
def cities(self):
"""
not finished
"""
lang = translation.get_language()
key = 'used_cities_%s'%lang
cached_cities = cache.get(key)
if cached_cities:
return cached_cities
else:
from exposition.models import Exposition
cities_id = [item['city_id'] for item in Exposition.objects.values('city_id').distinct()]
cities = list(self.language().filter(id__in=cities_id))
cache.set(key, cities, self.cache_time)
return cities
def hvad_to_dict(object):
"""

@ -22,7 +22,7 @@ from place_conference.models import PlaceConference
class AbstactSearchForm(forms.Form):
q = forms.CharField(label=_(u'Я ищу'), required=False)
q = forms.CharField(label=_(u'Я ищу'), required=False, widget=forms.TextInput(attrs={'placeholder':_(u'Тематика, слово или название')}))
w = forms.CharField(label=_(u'Где'), required=False)
models = None
data_with_parents = None
@ -99,6 +99,8 @@ class AbstactSearchForm(forms.Form):
return result
def get_places_display(self):
if self.is_valid():
area = self.cleaned_data['area']
@ -219,11 +221,7 @@ class AbstactSearchForm(forms.Form):
sqs = sqs.filter(place_filter)
return sqs#.order_by('data_begin')
import datetime
class ExpositionSearchForm(AbstactSearchForm):
search_url = '/expo/search/'
autocomplete_url = '/search-form/autosearch/exposition/'
@ -236,24 +234,21 @@ class ExpositionSearchForm(AbstactSearchForm):
#co = forms.CharField(label=_(u'Страна'), required=False, widget=forms.CheckboxSelectMultiple())
#tg = forms.CharField(label=_(u'Теги'), required=False, widget=forms.CheckboxSelectMultiple())
area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in Area.objects.all_sorted()],
area = forms.MultipleChoiceField(label=_(u'Регион'),
choices=[(item.id, item.name) for item in Area.objects.language().all()],
required=False, widget=forms.CheckboxSelectMultiple())
co = forms.MultipleChoiceField(label=_(u'Страна'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in Country.objects.select_related('exposition_country')\
.filter(exposition_country__country__isnull=False, translations__language_code=translation.get_language())\
.order_by('translations__name').distinct()]
choices=[(item.id, item.name) for item in Country.objects.expo_countries()]
)
ci = forms.MultipleChoiceField(label=_(u'Город'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in City.objects.select_related('exposition_city')\
.filter(exposition_city__city__isnull=False, translations__language_code=translation.get_language())\
.order_by('translations__name').distinct()]
choices=[(item.id, item.name) for item in City.used.expo_cities()]
)
fr = forms.DateField(required=False,
fr = forms.DateField(required=False, input_formats=('%d.%m.%Y',),
widget=forms.DateInput(attrs={'class': 'date', 'id': 'dateFrom',
'placeholder': _(u'дд.мм.гггг')}))
to = forms.DateField(required=False,
to = forms.DateField(required=False, input_formats=('%d.%m.%Y',),
widget=forms.DateInput(attrs={'class': 'date', 'id': 'dateTo',
'placeholder': _(u'дд.мм.гггг')}))
@ -269,6 +264,8 @@ class ExpositionSearchForm(AbstactSearchForm):
q = self.cleaned_data.get('q')
w = self.cleaned_data.get('w')
fr = self.cleaned_data.get('fr')
if not fr:
fr = datetime.date.today()
to = self.cleaned_data.get('to')
th = self.cleaned_data.get('th')
tg = self.cleaned_data.get('tg')
@ -276,6 +273,7 @@ class ExpositionSearchForm(AbstactSearchForm):
ci = self.cleaned_data.get('ci')
area = self.cleaned_data.get('area')
sqs = SearchQuerySet().models(Exposition).all()
if q:
@ -325,18 +323,14 @@ class PlaceSearchForm(AbstactSearchForm):
title = _(u'ПОИСК МЕСТ')
models = [PlaceExposition, PlaceConference]
# place fields
area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in Area.objects.all_sorted()],
area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in list(Area.objects.language().all())],
required=False, widget=forms.CheckboxSelectMultiple())
co = forms.MultipleChoiceField(label=_(u'Страна'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in Country.objects.select_related('exposition_country')\
.filter(exposition_country__country__isnull=False, translations__language_code=translation.get_language())\
.order_by('translations__name').distinct()]
choices=[(item.id, item.name) for item in list(Country.objects.expo_countries())]
)
ci = forms.MultipleChoiceField(label=_(u'Город'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in City.objects.select_related('exposition_city')\
.filter(exposition_city__city__isnull=False, translations__language_code=translation.get_language())\
.order_by('translations__name').distinct()]
choices=[(item.id, item.name) for item in list(City.used.expo_cities())]
)
#
place_type = forms.MultipleChoiceField(label=_(u'Тип'), required=False, choices=[])
@ -356,23 +350,19 @@ class CompanySearchForm(AbstactSearchForm):
required=False, widget=forms.CheckboxSelectMultiple())
tg = forms.CharField(label=_(u'Теги'), required=False, widget=forms.CheckboxSelectMultiple())
area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in Area.objects.all_sorted()],
area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in Area.objects.language().all()],
required=False, widget=forms.CheckboxSelectMultiple())
co = forms.MultipleChoiceField(label=_(u'Страна'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in Country.objects.select_related('exposition_country')\
.filter(exposition_country__country__isnull=False, translations__language_code=translation.get_language())\
.order_by('translations__name').distinct()]
choices=[(item.id, item.name) for item in Country.objects.expo_countries()]
)
ci = forms.MultipleChoiceField(label=_(u'Город'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in City.objects.select_related('exposition_city')\
.filter(exposition_city__city__isnull=False, translations__language_code=translation.get_language())\
.order_by('translations__name').distinct()]
choices=[(item.id, item.name) for item in City.used.expo_cities()]
)
def __init__(self, *args, **kwargs):
super(CompanySearchForm, self).__init__(*args, **kwargs)
self.theme_classes = {item.id:item.generate_search_class() for item in Theme.objects.all()}
self.theme_classes = {item.id:item.generate_search_class() for item in list(Theme.objects.language().all())}
def search(self):
q = self.cleaned_data.get('q')
@ -431,4 +421,5 @@ class EventSearchForm(forms.Form):
if w:
sqs = sqs.filter(where__contains=w)
return sqs
return sqs

@ -6,7 +6,7 @@ from functions.form_check import translit_with_separator
def pre_save_handler(sender, **kwargs):
obj = kwargs['instance']
if obj.language_code =='en':
if hasattr(obj, 'language_code') and obj.language_code =='en':
try:
name = getattr(obj, 'name')
obj.url = translit_with_separator(name)

@ -101,20 +101,27 @@ def fill_with_signal(model, obj, data):
# translated fields
fields = [field.name for field in model.translations.related.editable_fields() if field.name not in bad_fields]
# translate to first language(require)
# ! first save method call signal that fill require language to all translated fields
if not obj.id:
# new object
obj.translate(all_langs[0])
# go through all fields and set value
for field in fields:
setattr(obj, field, data.get('%s_%s'%(field, all_langs[0])).strip())
value = data.get('%s_%s'%(field, all_langs[0]), '')
if value:
setattr(obj, field, value.strip())
obj.save()
else:
trans_obj = model._meta.translations_model.objects.get(language_code = all_langs[0],
master__id=getattr(obj, 'id'))
for field in fields:
setattr(trans_obj, field, data.get('%s_%s'%(field, all_langs[0])).strip())
value = data.get('%s_%s'%(field, all_langs[0]), '')
if value:
setattr(trans_obj, field, value.strip())
trans_obj.save()
@ -126,7 +133,7 @@ def fill_with_signal(model, obj, data):
# start from second language
trans_obj = model._meta.translations_model.objects.get(language_code = code,master__id=getattr(obj, 'id'))
for field in fields:
val = data.get('%s_%s'%(field, code)).strip()
val = data.get('%s_%s'%(field, code), '').strip()
if val == '':
# get value from require translation
setattr(trans_obj, field, getattr(require_transl, field))

@ -11,7 +11,8 @@ import xlrd
from import_forms import ImportEventForm, ImportThemeForm, ImportTagForm, ImportOrganiserForm,\
ImportPlaceConferenceForm, ImportPlaceExpositionForm
from export_forms import ExportEventForm, ExportOrganiserForm, ExportThemeForm, ExportTagForm,\
ExportUserForm, ExportCompanyForm, ExportPlaceConferenceForm, ExportPlaceExpositionForm
ExportUserForm, ExportCompanyForm, ExportPlaceConferenceForm, ExportPlaceExpositionForm, ExportBlogForm,\
ExportCityForm
from django.views.generic import FormView
from django.contrib import messages
@ -78,6 +79,18 @@ class ExportPlaceExposition(ExportView):
form_class = ExportPlaceExpositionForm
success_url = '/admin/export-place_exposition'
class ExportBlog(ExportView):
form_class = ExportBlogForm
success_url = '/admin/export-blog/'
class ExportBlog(ExportView):
form_class = ExportBlogForm
success_url = '/admin/export-blog/'
class ExportCity(ExportView):
form_class = ExportCityForm
success_url = '/admin/export-city/'
from exposition.models import Exposition

@ -3,7 +3,7 @@ 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
ExportPlaceConference, ExportCompany, ExportUser, ExportBlog, ExportCity
urlpatterns = patterns('',
url(r'^import-event/$', ImportEvent.as_view()),
@ -21,5 +21,7 @@ urlpatterns = patterns('',
url(r'^export-place_conference/$', ExportPlaceConference.as_view()),
url(r'^export-user/$', ExportUser.as_view()),
url(r'^export-company/$', ExportCompany.as_view()),
url(r'^export-blog/$', ExportBlog.as_view()),
url(r'^export-city/$', ExportCity.as_view()),
)

@ -247,7 +247,6 @@ def to_phone(value):
value = value.replace(elem, '')
value = to_int(value)
print(value)
return value
@ -279,9 +278,16 @@ def save_halls(obj, value):
name = l[0].strip()
res.append({'area': area, 'name':name, 'number': number})
Hall.objects.filter(place_exposition=obj).delete()
for hall in res:
h = Hall(place_exposition = obj, name=hall.get('name'), number=hall.get('number'), capacity=hall.get('area'))
h.save()
try:
h.save()
except Exception, e:
print('---------------hall error---------')
print e
print('---------------------------------')
place_exp_sett = {
u'ID':{u'field': u'id', u'func': to_int},
@ -295,7 +301,7 @@ place_exp_sett = {
u'Тел.':{u'field': u'phone', u'func': to_phone},
u'Факс':{u'field': u'fax', u'func': to_phone},
u'Фото':{u'field': u'photo', u'func': save_photo, u'method': True},
u'Лого':{u'field': u'logo', u'func': save_file, u'method': True, u'purpose': 'logo'},
u'Лого':{u'field': u'logo', u'func': save_logo, u'method': True},
u'Веб-сайт':{u'field': u'web_page', u'func': unicode},
u'Email':{u'field': u'email', u'func': unicode},
u'Карта проезда':{u'field': u'map', u'func': save_file, u'method': True, u'purpose': 'map'},
@ -324,6 +330,17 @@ place_exp_sett = {
u'Мобильное приложение':{u'field': u'mobile_application', u'func': bool},
}
article_sett = {
u'ID':{u'field': u'id', u'func': to_int},
u'Заголовок':{u'field': u'main_title', u'func': unicode},
u'Описание':{u'field': u'description', u'func': unicode},
u'Айди автора':{u'field': u'author', u'func': to_user},
u'Создана':{u'field': u'created', u'func': to_datetime}
}
event_sett = {
u'ID':{u'field': u'id', u'func': to_int},
u'Url':{u'field': u'url', u'func': unicode},
@ -332,16 +349,19 @@ event_sett = {
u'Дата начала:(YYYY-MM-DD)':{u'field': u'data_begin', u'func': to_date},
u'Дата окончания:(YYYY-MM-DD)':{u'field': u'data_end', u'func': to_date},
u'Страна':{u'field': u'country', u'func': to_country},
u'Город':{u'field': u'city', u'func': to_city, 'extra_values': 'country'},
u'Место проведения':{u'field': u'place', u'func': to_place},
u'Город':{u'field': u'city_id', u'func': to_city, 'extra_values': 'country'},
#u'Место проведения':{u'field': u'place', u'func': to_place},
u'ID Тематики':{u'field': u'theme', u'func': to_theme, u'method': True},###
u'Теги':{u'field': u'tag', u'func': to_tag, u'method': True},
#u'Организатор №1':{u'field': u'organiser', u'func': to_tag},####
#u'Организатор №2':{u'field': u'organiser', u'func': to_tag},####
u'Описание события':{u'field': u'description', u'func': unicode},
u'Основные темы':{u'field': u'main_themes', u'func': unicode},
u'Условия и скидка':{u'field': u'discount_description', u'func': unicode},
u'Периодичность':{u'field': u'periodic', u'func': to_periodic},###
u'Аудитория':{u'field': u'audience', u'func': to_audience},
u'Официальный веб-сайт':{u'field': u'web_page', u'func': to_url},
u'Линк на регистрацию':{u'field': u'link', u'func': to_url},
u'Экспонируемые продукты':{u'field': u'products', u'func': unicode},
u'Время работы':{u'field': u'time', u'func': unicode},
u'Логотип':{u'field': u'logo', u'func': save_logo, u'method': True},
@ -366,7 +386,7 @@ event_sett = {
u'Min_Pack кв.м.':{u'field': u'min_closed_equipped_area', u'func': to_int},
u'Max_Pack кв.м.':{u'field': u'max_closed_equipped_area', u'func': to_int},
u'Открытая площадь':{u'field': u'max_open_area', u'func': to_int},
u'Мин. Площадь кв.м.':{u'field': u'min_open_area', u'func': to_int},
u'Мин. Площадь кв.м.':{u'field': u'min_stand_size', u'func': to_int},
u'Регистрационный взнос':{u'field': u'registration_payment', u'func': to_int},
u'Примечание по участии':{u'field': u'participation_note', u'func': unicode},
u'Крайний срок подачи заявки':{u'field': u'application_deadline', u'func': to_date},

@ -1,11 +1,14 @@
# -*- coding: utf-8 -*-
from django import forms
from django.conf import settings
from django.utils import translation
from theme.models import Theme, Tag
from country.models import Country
from city.models import City
from organiser.models import Organiser
from accounts.models import User
from company.models import Company
from article.models import Article
from place_exposition.models import PlaceExposition
from place_conference.models import PlaceConference
from django.db.models.loading import get_model
@ -149,6 +152,25 @@ class ExportCompanyForm(ExportForm):
def get_fname(self):
return 'companies.xls'
class ExportBlogForm(ExportForm):
model = Article
def get_fname(self):
return 'blogs.xls'
def get_objects(self, data):
translation.activate(data['language'])
return self.model.objects.blogs()
class ExportCityForm(ExportForm):
model = City
def get_fname(self):
return 'cities.xls'
def get_objects(self, data):
translation.activate(data['language'])
return self.model.used.all()
class ExportEventForm(forms.Form):

@ -12,6 +12,7 @@ from city.models import City
from theme.models import Theme, Tag
from functions.files import get_alternative_filename
from exposition.models import BIT_AUDIENCE
from accounts.models import User
def to_int(val):
@ -29,19 +30,32 @@ def to_date(value):
return None
if isinstance(value, unicode) or isinstance(value, str):
t = time.strptime(value, "%d.%m.%Y")
try:
t = time.strptime(value, "%d.%m.%Y")
except ValueError:
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)
def to_datetime(value):
if not value:
return None
if isinstance(value, unicode) or isinstance(value, str):
t = time.strptime(value, "%Y-%m-%d %H:%M:%S")
return time.strftime("%Y-%m-%d %H:%M:%S", t)
def to_country(value):
try:
query = get_translation_aware_manager(Country)
country = query.filter(name=value)[0]
return country
except IndexError:
print('---------------------')
print(value.encode('utf8'))
print('AAAAAAAA')
return None
def to_city(value, lang, country):
@ -51,9 +65,9 @@ def to_city(value, lang, country):
# except IndexError if no found
city = City.objects.filter(translations__name=value, country=country)[0]
# print(city)
return city
return city.id
except IndexError:
print('---------------------')
print('---------city error------------')
print(value.encode('utf8'))
print('---------------------')
return None
@ -70,6 +84,9 @@ def to_theme(obj, value):
else:
theme_ids = value.split(',')
if theme_ids == ['']:
return
obj.theme.clear()
obj.theme.add(*Theme.objects.filter(id__in=theme_ids))
def to_tag(obj,value):
@ -78,6 +95,7 @@ def to_tag(obj,value):
names = value.split(',')
translation.activate('en')
if names:
obj.tag.clear()
obj.tag.add(*Tag.objects.filter(translations__name__in=names, theme__in=obj.theme.all()))
else:
return
@ -140,16 +158,23 @@ def save_logo(obj, path):
logo_path = obj.logo.field.upload_to
full_path = settings.MEDIA_ROOT + logo_path
alt_name = get_alternative_filename(full_path, file_name)
try:
alt_name = get_alternative_filename(full_path, file_name)
except UnicodeEncodeError:
return None
download_to = full_path+alt_name
if path.startswith('http://') or path.startswith('https://'):
url = path
else:
elif path.startswith('/'):
url = 'http://expomap.ru' + path
elif path.startswith('images'):
url = 'http://expomap.ru/' + path
else:
return None
try:
response = urllib2.urlopen(url, timeout=15)
@ -181,4 +206,11 @@ def check_quality_label(obj, value, label):
return bit
if value:
setattr(bit, label, True)
return bit
return bit
def to_user(value):
try:
return User.objects.get(id=value)
except User.DoesNotExist:
return User.objects.get(id=1)

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.core.context_processors import csrf
from django.conf import settings
from django.forms.formsets import BaseFormSet, formset_factory
from django.forms.models import modelformset_factory
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.decorators import login_required
#models and forms
from models import MetaSetting
from forms import MetaForm, MetaFilterForm
from functions.admin_views import AdminListView, AdminView
class MetaListView(AdminListView):
template_name = 'admin/meta/meta_list.html'
form_class = MetaFilterForm
model = MetaSetting
class MetaView(AdminView):
form_class = MetaForm
model = MetaSetting
success_url = '/admin/meta/all/'
template_name = 'admin/meta/meta_setting.html'
def form_valid(self, form):
self.set_obj()
expo = form.save(obj=self.obj)
return HttpResponseRedirect(self.success_url)
def get_form(self, form_class):
if self.request.POST:
return super(MetaView, self).get_form(form_class)
obj = self.set_obj()
if obj:
data = {'name':obj.name}
for code, name in settings.LANGUAGES:
trans_obj = self.model._meta.translations_model.objects.get(language_code = code,master__id=obj.id) #access to translated fields
data['title_%s' % code] = trans_obj.title
data['description_%s' % code] = trans_obj.description
data['keywords_%s' % code] = trans_obj.keywords
data['h1_%s' % code] = trans_obj.h1
form =form_class(initial=data)
return form
else:
return form_class()
def get_context_data(self, **kwargs):
context = super(MetaView, self).get_context_data(**kwargs)
obj = self.set_obj()
return context

@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from admin import MetaListView, MetaView
urlpatterns = patterns('conference.admin',
url(r'^all/$', MetaListView.as_view()),
#url(r'^change/(?P<url>.*)/$', 'conference_change'),
url(r'^(?P<id>.*)/$', MetaView.as_view()),
url(r'^$', MetaView.as_view()),
)

@ -0,0 +1,23 @@
from meta.views import Meta
def add_meta(view):
def wrapper(request, *args, **kwargs):
"""
meta = Meta(
title=title,
description=description,
keywords=keywords,
meta_extras = {
'viewport': 'width=device-width, initial-scale=1.0, minimum-scale=1.0'
}
'extra_custom_props': [
('http-equiv', 'Content-Type', 'text/html; charset=UTF-8'),
]
)
"""
r = view(request, *args, **kwargs)
r.context_data = {'foo': 'bar'}
return r.render()
return wrapper

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
from django import forms
from django.conf import settings
from models import MetaSetting
from functions.translate import fill_with_signal
from functions.admin_forms import AdminFilterForm
class MetaForm(forms.Form):
name = forms.CharField(label=u'Название страницы')
def __init__(self, *args, **kwargs):
"""
create dynamical translated fields fields
"""
super(MetaForm, self).__init__(*args, **kwargs)
#creates translated forms example: name_ru, name_en
# len(10) is a hack for detect if settings.LANGUAGES is not configured it return all langs
if len(settings.LANGUAGES) in range(10):
for lid, (code, name) in enumerate(settings.LANGUAGES):
# uses enumerate for detect iteration number
# first iteration is a default lang so it required fields
required = True if lid == 0 else False
self.fields['title_%s' % code] = forms.CharField(label=u'Title', required=required,
widget=forms.TextInput(attrs={'style':'width: 550px'}))
self.fields['description_%s' % code] = forms.CharField(label=u'Description', required=required,
widget=forms.TextInput(attrs={'style':'width: 550px'}))
self.fields['keywords_%s' % code] = forms.CharField(label=u'Keywords', required=False,
widget=forms.TextInput(attrs={'style':'width: 550px'}))
self.fields['h1_%s' % code] = forms.CharField(label=u'H1', required=False,
widget=forms.TextInput(attrs={'style':'width: 550px'}))
def save(self, obj=None):
data = self.cleaned_data
if not obj:
meta = MetaSetting()
else:
meta = obj
meta.name = data['name']
# fill translated fields and save object
fill_with_signal(MetaSetting, meta, data)
meta.save()
class MetaFilterForm(AdminFilterForm):
model = MetaSetting

@ -1,8 +1,44 @@
# -*- coding: utf-8 -*-
from django.db import models
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from django.utils import translation
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from pymorphy.django_conf import default_morph as morph
from functions.signal_handlers import post_save_handler
# additional funcs
MONTHES = {'jan': _(u'январе'), 'feb': _(u'феврале'), 'mar': _(u'марте'), 'apr': _(u'апреле'),
'may': _(u'мае'), 'jun': _(u'июне'), u'jul': _(u'июле'), 'aug': _(u'августе'),
'sep': _(u'сентябре'), 'oct': _(u'октябре'), 'nov': _(u'ноябре'), 'dec': _(u'декабре'),}
def get_month_inflect(value, key):
return {key: MONTHES.get(value, '') }
def get_obj_inflect(obj, key):
if translation.get_language() == 'ru':
result = {key: getattr(obj, 'inflect', '')}
else:
result = {key: getattr(obj, 'name', '')}
return result
def get_theme_inflect(obj, key):
if translation.get_language() == 'ru':
result = {'theme_inflect': getattr(obj, 'inflect', ''),
'theme_name': getattr(obj, 'name', '')}
else:
result = {'theme_inflect': getattr(obj, 'name', ''),
'theme_name': getattr(obj, 'name', '')}
return result
def get_tag_inflect(obj, key):
if translation.get_language() == 'ru':
result = {'tag_inflect': getattr(obj, 'inflect', ''),
'tag_name': getattr(obj, 'name', '')}
else:
result = {'tag_inflect': getattr(obj, 'name', ''),
'tag_name': getattr(obj, 'name', '')}
return result
class MetaSetting(TranslatableModel):
name = models.CharField(max_length=100, unique=True)
@ -13,32 +49,41 @@ class MetaSetting(TranslatableModel):
h1 = models.CharField(max_length=255, blank=True),
)
params = {'EXPONAME':{'name': 'name'},
'EXPONAME_YA':{'name': 'name', 'inflect': True},
'EXPOCOUNTRY':{'name': 'country'},
'EXPOCOUNTRY_YA':{'name': 'country', 'inflect': True},
'EXPOPLACE':{'name': 'place'},
'EXPOCITY':{'name': 'city'},
'EXPOTHEME':{'name': 'theme'},
'EXPOTAG':{'name': 'tag'},
'EXPOMONTH':{'name': 'month'},
'EXPOYEAR':{'name': 'year'},
}
object_params = {'object_name': 'name', 'object_title': 'main_title', 'city': 'city', 'country': 'country'}
params = {'month': get_month_inflect, 'country': get_obj_inflect, 'city': get_obj_inflect,
'theme': get_theme_inflect, 'tag': get_tag_inflect}
monthes = {'jan': _(u'январе'), 'feb': _(u'феврале'), 'mar': _(u'марте'), 'apr': _(u'апреле'),
'may': _(u'мае'), 'jun': _(u'июне'), u'jul': _(u'июле'), 'aug': _(u'августе'),
'sep': _(u'сентябре'), 'oct': _(u'октябре'), 'nov': _(u'ноябре'), 'dec': _(u'декабре'),}
def __unicode__(self):
return self.name
def generate_meta(self, obj):
def generate_meta(self, params, obj=None):
"""
obj must be in current language
"""
lang = translation.get_language()
params = {'EXPONAME': getattr(obj, 'name', '')}
updates = {}
if obj:
for key, value in self.object_params.iteritems():
updates.update({key: getattr(obj, value, '')})
for key, value in params.iteritems():
if key in self.params:
updates.update(self.params[key](value, key))
params.update(updates)
tr = self.translations.get(language_code=lang)
title = tr.title.format(**params)
description = tr.description.format(**params)
keywords = []#tr.keywords.format(**params)
h1 = tr.h1.format(**params)
return {'title': title, 'description': description, 'keywords': keywords, 'h1': h1}
def get_param(self, obj, field):
@ -51,6 +96,21 @@ class MetaSetting(TranslatableModel):
return s
def get_title(self):
title = self.title
return title
def get_h1(self):
h1 = self.h1
return h1
def get_description(self):
description = self.description
return description
def get_keywords(self):
keywords = self.keywords
return []
post_save.connect(post_save_handler, sender=MetaSetting)

@ -1,6 +1,7 @@
from __future__ import unicode_literals
from django.core.exceptions import ImproperlyConfigured
from models import MetaSetting
from . import settings
@ -150,18 +151,40 @@ class MetadataMixin(object):
return self.site_name or settings.SITE_NAME
def get_context_data(self, **kwargs):
context = super(MetadataMixin, self).get_context_data(**kwargs)
context['meta'] = self.get_meta_class()(
use_og=self.use_og,
use_sites=self.use_sites,
title=self.get_meta_title(context=context),
h1=self.get_meta_h1(context=context),
description=self.get_meta_description(context=context),
keywords=self.get_meta_keywords(context=context),
image=self.get_meta_image(context=context),
url=self.get_meta_url(context=context),
object_type=self.get_meta_object_type(context=context),
site_name=self.get_meta_site_name(context=context),
)
return context
meta_id = self.kwargs.get('meta_id')
if not meta_id:
meta_id = kwargs.get('meta_id')
if meta_id:
try:
meta_set = MetaSetting.objects.language().get(id=meta_id)
except MetaSetting.DoesNotExist:
return context
params = dict(self.kwargs)
if getattr(self, 'object', None):
data = meta_set.generate_meta(params, self.object)
else:
data = meta_set.generate_meta(params)
self.title = data.get('title')
self.h1 = data.get('h1')
self.description = data.get('description')
self.keywords = data.get('keywords', [])
context['meta'] = self.get_meta_class()(
use_og=self.use_og,
use_sites=self.use_sites,
title=self.get_meta_title(context=context),
h1=self.get_meta_h1(context=context),
description=self.get_meta_description(context=context),
keywords=self.get_meta_keywords(context=context),
image=self.get_meta_image(context=context),
url=self.get_meta_url(context=context),
object_type=self.get_meta_object_type(context=context),
site_name=self.get_meta_site_name(context=context),
)
return context

@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
from django.core.management.base import BaseCommand, CommandError
from organiser.models import Organiser
from theme.models import Theme, Tag
from functions.form_check import translit_with_separator
from accounts.models import User
import MySQLdb
from MySQLdb.cursors import DictCursor
@ -21,9 +23,9 @@ def convert_to_int(st):
class Command(BaseCommand):
def handle(self, *args, **options):
db = MySQLdb.connect(host="localhost",
user="root",
user="kotzilla",
passwd="qazedc",
db="expomap_ru",
db="old_expomap",
charset='utf8',
cursorclass=DictCursor)
@ -31,18 +33,18 @@ class Command(BaseCommand):
sql = """SELECT DISTINCT(customers_company) as name, specialize, otrasly as theme, tags, adress,
phone, fax, email, website, twitter, about, customers_company.url
sql = """SELECT DISTINCT(customers_company) as name, customers_email_address as user_email, specialize, otrasly as theme, tags, adress,
phone, fax, email, website, twitter, about, customers_company.url, company_last_modified as modified
FROM customers
LEFT JOIN customers_company
ON customers.customers_company=customers_company.title
ON customers.customers_id = customers_company.customers_id
WHERE customers_status = 4
"""
cursor.execute(sql)
res = cursor.fetchall()
print(res[0].get('user_email'))
for o in res:
if not o.get('name'):
@ -66,7 +68,7 @@ class Command(BaseCommand):
organiser.description = o.get('about')
if organiser.name:
print('not_saved: %s'%o['name'])
print('not_saved: %s'%o['name'].encode('utf8'))
organiser.save()
print('saved: %s'%str(organiser))
@ -75,12 +77,10 @@ class Command(BaseCommand):
if theme_id:
try:
theme = Theme.objects.get(id=theme_id)
organiser.theme.add(theme)
except Theme.DoesNotExist:
continue
organiser.theme.add(theme)
pass
if not theme:
continue
tags = o.get('tags')
if tags:
@ -104,5 +104,14 @@ class Command(BaseCommand):
organiser.save()
print(organiser)
user_email = o.get('user_email')
if user_email:
try:
user = User.objects.get(username=user_email)
user.organiser = organiser
user.save()
except User.DoesNotExist:
print('no user with this email: %s'%user_email)
print('success')

@ -75,6 +75,7 @@ class Organiser(TranslatableModel):
#fields saves information about creating and changing model
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
active = models.NullBooleanField(default=0)
def __unicode__(self):
return self.lazy_translation_getter('name', self.pk)

@ -0,0 +1,114 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html style="margin: 0; padding: 0; height: 100%;">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
</head>
<body style="margin: 0; padding: 0; min-height: 100%; background: #f4f2ee;">
<table cellpadding="0" cellspacing="0" border="0" width="100%" height="100%" bgcolor="#f4f2ee" style="font-family: Arial, sans-serif; background: #f4f2ee;">
<tr>
<td align="center" style="padding: 50px 0">
<table cellpadding="0" cellspacing="0" border="0" width="600" style="width: 600px;">
<tr>
<td style="vertical-align: top;">
<div class="logo">
<a style="text-decoration: none; color: #a2a2a2; font-size: 12px;" href="#">
<img src="cid:logo" alt="Expomap.ru" />
<b style="display: block; padding-left: 67px; margin-top: -5px;">Выставки, конференции, семинары</b>
</a>
</div>
</td>
<td style="vertical-align: top; padding-top: 22px;">
<ul class="t-links" style="margin: 0 0 15px; padding: 0; list-style: none; text-align: right; font-size: 16px; line-height: 17px; font-weight: bold;">
<li style="display: inline-block;"><a style="text-decoration: none; color: #ff6600" href="#">СОБЫТИЯ</a></li>
<li style="display: inline-block; margin-left: 20px;"><a style="text-decoration: none; color: #ff6600" href="#">МЕСТА</a></li>
<li style="display: inline-block; margin-left: 20px;"><a style="text-decoration: none; color: #ff6600" href="#">УЧАСТНИКИ</a></li>
</ul>
<ul class="soc-media-buttons" style="margin: 0; padding: 0; list-style: none; text-align: right;">
<li style="display: inline-block;"><a href="#"><img src="cid:rss" title="RSS" alt="RSS" /></a></li>
<li style="display: inline-block; margin-left: 5px;"><a href="#"><img src="cid:fb" title="Facebook" alt="Facebook" /></a></li>
<li style="display: inline-block; margin-left: 5px;"><a href="#"><img src="cid:linkedin" title="LinkedIn" alt="LinkedIn" /></a></li>
<li style="display: inline-block; margin-left: 5px;"><a href="#"><img src="cid:vk" title="В контакте" alt="В контакте" /></a></li>
<li style="display: inline-block; margin-left: 5px;"><a href="#"><img src="cid:twit" title="Twitter" alt="Twitter" /></a></li>
</ul>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" border="0" width="600" style="width: 600px; margin-bottom: 10px;">
<tr>
<td style="padding: 20px 0 0;"><p style="display: block; padding: 25px 30px; text-decoration: none; background: #ff6600; color: #ffffff; font-size: 20px; line-height: 26px; margin-bottom: 0;" >Воостановление пароля на портале <a href="http://expomap.ru/" style="color: #ffffff;text-decoration: none;border-bottom: 1px dashed #ee3824;">Expomap</a></p></td>
</tr>
<tr>
<td style="padding: 10px 30px 15px; background: #faf9f7;">
<table cellpadding="0" cellspacing="0" border="0" width="540" style="margin-bottom: 15px;">
<tr valign="top">
<td style="padding: 15px 0 36px 0;">
<p style="font-weight: bold;color: #003e79;margin: 0;">Добрый день, {{ user.first_name }}!</p>
</td>
</tr>
<tr valign="top">
<td style="padding: 0 0 23px 0;">
Вы или кто-то еще сделал запрос на сброс пароля на сайте <a href="{{ domain }}" style="text-decoration: none;border-bottom: 1px dashed #ee3824;color: #645a5a;">{{ domain }}</a>
</td>
</tr>
<tr valign="top">
<td style="padding: 0 0 32px 0;">
Вы можете восстановить доступ, нажав на кнопку ниже и указав новый пароль:
</td>
</tr>
<tr valign="top">
<td style="padding: 0 0 32px 0; text-align: center;">
<a class="button" style="display: inline-block; padding: 4px 10px 3px; text-decoration: none; color: #2592c5; font-size: 14px; font-weight: bold; line-height: 14px; border: 1px solid #90c7e0; text-transform: uppercase; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; width: 336px;" href="http{% if secure %}s{% endif %}://{{ site.domain }}{% url "password_reset_reset" token %}">востановить пароль</a>
</td>
</tr>
<tr valign="top">
<td style="padding: 0 0 20px 0; text-align: left; ">
Если вы не хотите сбрасывать пароль, просто <span style="border-bottom: 1px dashed #ee3824;">проигнорируйте</span> это сообщение
</td>
</tr>
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" border="0" width="600" style="width: 600px; border-bottom: 1px dotted #cccccc;">
<tr>
<td style="vertical-align: top; padding: 15px 0 10px;">
<div class="logo">
<a style="text-decoration: none; color: #a2a2a2; font-size: 12px;" href="#">
<img src="cid:logo2" alt="Expomap.ru" />
</a>
</div>
</td>
<td style="vertical-align: top; padding: 25px 0 5px;">
<ul class="t-links" style="margin: 0 0 15px; padding: 0; list-style: none; text-align: right; font-size: 14px; line-height: 15px; font-weight: bold;">
<li style="display: inline-block;"><a style="text-decoration: none; color: #ff6600" href="#">СОБЫТИЯ</a></li>
<li style="display: inline-block; margin-left: 20px;"><a style="text-decoration: none; color: #ff6600" href="#">МЕСТА</a></li>
<li style="display: inline-block; margin-left: 20px;"><a style="text-decoration: none; color: #ff6600" href="#">УЧАСТНИКИ</a></li>
</ul>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" border="0" width="600" style="width: 600px; font-size: 12px; line-height: 15px;">
<tr>
<td style="vertical-align: top; padding: 15px 0 15px; color: #a2a2a2; text-align: right;">
© 2018 — 2013 <a style="color: #a2a2a2; text-decoration: none;" href="#">Expomap.ru</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

@ -1,15 +1,18 @@
import datetime
from django.core.mail import EmailMessage
from django.conf import settings
from django.contrib.sites.models import Site, RequestSite
from django.core import signing
from django.core.mail import send_mail
from django.template import Context
from django.core.urlresolvers import reverse, reverse_lazy
from django.shortcuts import get_object_or_404, redirect
from django.http import Http404
from django.template import loader
from django.utils import timezone
from django.views import generic
from django.template.loader import get_template
from email.MIMEImage import MIMEImage
from .forms import PasswordRecoveryForm, PasswordResetForm
from .utils import get_user_model, get_username
@ -52,7 +55,7 @@ class Recover(SaltMixin, generic.FormView):
form_class = PasswordRecoveryForm
template_name = 'password_reset/recovery_form.html'
success_url_name = 'password_reset_sent'
email_template_name = 'password_reset/recovery_email.txt'
email_template_name = 'password_reset/recovery_email_expo.html'
email_subject_template_name = 'password_reset/recovery_email_subject.txt'
search_fields = ['username', 'email']
@ -85,12 +88,35 @@ class Recover(SaltMixin, generic.FormView):
'token': signing.dumps(self.user.pk, salt=self.salt),
'secure': self.request.is_secure(),
}
body = loader.render_to_string(self.email_template_name,
context).strip()
#body = loader.render_to_string(self.email_template_name,
# context).strip()
message = get_template(self.email_template_name).render(Context(context))
subject = loader.render_to_string(self.email_subject_template_name,
context).strip()
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL,
[self.user.email])
msg = EmailMessage(subject, message, settings.DEFAULT_FROM_EMAIL, [self.user.email])
msg.content_subtype = "html"
images =(('/img/logo_reg.png', 'logo'),
('/img/soc-medias/sm-icon-rss.png', 'rss'),
('/img/soc-medias/sm-icon-fb.png', 'fb'),
('/img/soc-medias/sm-icon-lin.png', 'linkedin'),
('/img/soc-medias/sm-icon-vk.png', 'vk'),
('/img/soc-medias/sm-icon-twit.png', 'twit'),
('/img/mail-logo-2.jpg','logo2'))
for img in images:
fp = open(settings.STATIC_ROOT+img[0], 'rb')
msg_img = MIMEImage(fp.read())
fp.close()
msg_img.add_header('Content-ID', '<'+img[1]+'>')
msg.attach(msg_img)
msg.send()
#send_mail(subject, body, settings.DEFAULT_FROM_EMAIL,
# [self.user.email])
def form_valid(self, form):
self.user = form.cleaned_data['user']

@ -20,7 +20,7 @@ import random
#custom fields
from functions.custom_views import objects_list, delete_object
from functions.views_help import get_referer
from functions.admin_views import AdminView, AdminListView, upload_photo
from functions.admin_views import AdminView, AdminListView, upload_photo, FormView
def exposition_all(request):
@ -282,3 +282,28 @@ class PlaceExpositionListView(AdminListView):
def upload_place_photo(request, place_id):
return upload_photo(request, place_id, PlaceExposition)
def edit_hall(request, place_url, hall_id):
place = get_object_or_404(PlaceExposition, url=place_url)
hall = get_object_or_404(Hall, id=hall_id)
if request.POST:
form = HallForm(request.POST)
if form.is_valid():
form.save(place, hall_id)
return HttpResponseRedirect('/admin/place_exposition/%s/'%place.url)
else:
data = {'capacity': hall.capacity, 'number': hall.number}
for code, name in settings.LANGUAGES:
trans_obj = Hall._meta.translations_model.objects.get(language_code = code, master__id=hall.id) #access to translated fields
data['name_%s'%code] = trans_obj.name
form = HallForm(initial=data)
context = {'form': form, 'languages': settings.LANGUAGES}
context.update(csrf(request))
return render_to_response('admin/place_exposition/hall.html', context)

@ -7,10 +7,11 @@ urlpatterns = patterns('place_exposition.admin',
url(r'^add-hall/(?P<place_id>.*)/$', 'add_hall'),
url(r'^delete-hall/(?P<hall_id>.*)/$', 'delete_hall'),
url(r'^upload-photo/(?P<place_id>.*)/$', 'upload_place_photo'),
url(r'^hall/(?P<place_url>.*)/(?P<hall_id>.*)/$', 'edit_hall'),
url(r'^all/$', PlaceExpositionListView.as_view()),
#url(r'^add.*/$', 'exposition_add'),
#url(r'^delete/(?P<url>.*)/$', 'exposition_delete'),
url(r'^delete/(?P<url>.*)/$', 'exposition_delete'),
#url(r'^change/(?P<url>.*)/$', 'exposition_change'),
#url(r'^copy/(?P<url>.*)/$', 'place_exposition_copy'),
url(r'^(?P<url>.*)/$', PlaceExpositionView.as_view()),

@ -27,13 +27,13 @@ class ExpositionForm(forms.Form):
"""
types = [(item1, item2) for item1, item2 in EXPOSITION_TYPE]
type = forms.ChoiceField(required=False, choices=types)
logo = forms.ImageField(label='Logo', required=False)
logo = forms.ImageField(label='Logo', required=False, max_length=500)
country = forms.ChoiceField(label='Страна', choices=[(c.id, c.name) for c in Country.objects.all()])
# creates select input with empty choices cause it will be filled with ajax
city = forms.CharField(label='Город', widget=forms.HiddenInput())
address = forms.CharField(label='Адресс', widget=LocationWidget, required=False)
address = forms.CharField(label='Адрес', widget=LocationWidget, required=False)
phone = forms.CharField(label='Телефон', required=False,
widget=forms.TextInput(attrs={'placeholder': 'Введите телефон'}))
@ -48,7 +48,7 @@ class ExpositionForm(forms.Form):
widget=forms.TextInput(attrs={'placeholder': 'Год основания'}))
total_area = forms.CharField(label='Общая выставочная площадь', required=False,
widget=forms.TextInput(attrs={'placeholder': 'Общая выст. площадь'}))
closed_area = forms.CharField(label='Закрытая выствочная площадь', required=False,
closed_area = forms.CharField(label='Закрытая выставочная площадь', required=False,
widget=forms.TextInput(attrs={'placeholder': 'Закр. выст. площадь'}))
open_area = forms.CharField(label='Открытая выставочная площадь', required=False,
widget=forms.TextInput(attrs={'placeholder': 'Откр. выст. площадь'}))
@ -62,10 +62,10 @@ class ExpositionForm(forms.Form):
children_room = forms.BooleanField(label='Детская комната', required=False)
disabled_service = forms.BooleanField(label='Сервис для инвалидов', required=False)
conference_centre = forms.BooleanField(label='Конгресс-центр', required=False)
business_centre = forms.BooleanField(label='Бизнес центр', required=False)
business_centre = forms.BooleanField(label='Бизнес-центр', required=False)
online_registration = forms.BooleanField(label='Онлайн регистрация', required=False)
cafe = forms.BooleanField(label='Кафе', required=False)
terminals = forms.BooleanField(label='Информационые терминалы', required=False)
terminals = forms.BooleanField(label='Информационные терминалы', required=False)
parking = forms.BooleanField(label='Парковка', required=False)
press_centre = forms.BooleanField(label='Пресс-центр', required=False)
mobile_application = forms.BooleanField(label='Мобильное приложение', required=False)
@ -278,8 +278,10 @@ class HallForm(forms.ModelForm):
class HallForm(forms.Form):
url = '/admin/place_exposition/add-hall/'
number = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:30px'}),required=False)
capacity = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:60px'}), required=False)
number = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:30px'}),required=False,
label='Номер')
capacity = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:60px'}), required=False,
label='Вместимость')
def __init__(self, *args, **kwargs):
"""
create dynamical translated fields fields
@ -294,11 +296,6 @@ class HallForm(forms.Form):
required = True if lid == 0 else False
self.fields['name_%s' % code] = forms.CharField(label='Название', required=required)
def clean_number(self):
cleaned_data = super(HallForm, self).clean()
number = cleaned_data.get('number').strip()
return is_positive_integer(number, 'Номер должен состоять из цифр')
def clean_capacity(self):
cleaned_data = super(HallForm, self).clean()
capacity = cleaned_data.get('capacity').strip()
@ -314,6 +311,7 @@ class HallForm(forms.Form):
hall.number = data['number']
hall.place_exposition = place_exposition
fill_with_signal(Hall, hall, data)
hall.save()
return hall

@ -27,15 +27,9 @@ def handle_place(place):
place.save()
class Command(BaseCommand):
def handle(self, *args, **options):
for place in PlaceExposition.objects.all('en'):
if place.files.filter(purpose='logo').exists():
handle_place(place)
print(place)
print(place)

@ -1,99 +1,114 @@
# -*- coding: utf-8 -*-
from django.core.management.base import BaseCommand, CommandError
import xlrd
from place_exposition.models import PlaceExposition
import xlrd, xlwt
from import_xls.excel_settings import import_settings, place_exp_sett
from django.conf import settings
from import_xls.import_forms import google_address
PLACE_FILE = settings.MEDIA_ROOT+'import/places_ru.xls'
class Command(BaseCommand):
def handle(self, *args, **options):
f = open(settings.MEDIA_ROOT+'/import/places_ru.xlsx', 'r')
f = open(PLACE_FILE, 'r')
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)]
labels = [label for label in row_list[0]]
for row_number, row in enumerate(row_list):
existing = 0
for row_number, row in enumerate(row_list[1:]):
new = 0
# go through all rows in file
if row_number > 0:
# first field is label
if row[0] != '':
# in first column ids
if row[0] != '':
# in first column ids
try:
object = PlaceExposition.objects.language('ru').get(id=int(row[0]))
except ValueError:
object = PlaceExposition()
object.translate('ru')
except PlaceExposition.DoesNotExist:
object = PlaceExposition(id= int(row[0]))
object.translate('ru')
else:
# if id blank - its a new place
object = PlaceExposition
try:
object = PlaceExposition.objects.language('ru').get(id=int(row[0]))
existing += 1
except ValueError:
object = PlaceExposition()
object.translate('ru')
methods = []
for col_number, cell in enumerate(row):
# go through row cells
# field name current cell
label = labels[col_number]
setting = place_exp_sett.get(label)
if setting is None:
continue
new = 1
if setting.get('method'):
if cell != "":
methods.append({'func': setting['func'], 'value': cell, 'purpose': setting.get('purpose')})
continue
except PlaceExposition.DoesNotExist:
object = PlaceExposition(id= int(row[0]))
object.translate('ru')
existing += 1
new = 1
else:
# if id blank - its a new place
object = PlaceExposition
object.translate('ru')
field_name = setting['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, 'ru', getattr(object, extra_value))
else:
value = func(cell)
#if field_name =='adress':
# setattr(object, 'address', google_address(value))
setattr(object, field_name, value)
object.save()
print('post save %s'% str(object))
"""
try:
print(object)
#object.save()
except IntegrityError:
methods = []
for col_number, cell in enumerate(row):
# go through row cells
# field name current cell
label = labels[col_number]
setting = place_exp_sett.get(label)
if setting is None:
continue
#url = object.url + translit_with_separator(object.city.name)
#object.url = url
#object.save()
"""
for method in methods:
func = method['func']
if method.get('purpose'):
try:
func(object, method['value'], method['purpose'])
except:
continue
if setting.get('method'):
if cell != "":
methods.append({'func': setting['func'], 'value': cell, 'purpose': setting.get('purpose')})
continue
field_name = setting['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, 'ru', getattr(object, extra_value))
else:
value = func(cell)
#if field_name =='adress':
# setattr(object, 'address', google_address(value))
if field_name == 'city' and new == 0:
pass
else:
try:
func(object, method['value'])
except:
continue
setattr(object, field_name, value)
except ValueError, e:
print(value, field_name)
object.save()
print('post save %s'% str(object))
"""
try:
print(object)
#object.save()
except IntegrityError:
continue
#url = object.url + translit_with_separator(object.city.name)
#object.url = url
#object.save()
"""
for method in methods:
func = method['func']
if method.get('purpose'):
try:
func(object, method['value'], method['purpose'])
except:
continue
else:
try:
func(object, method['value'])
except:
continue

@ -78,8 +78,9 @@ class PlaceExposition(TranslatableModel, ExpoMixin):
press_centre = models.NullBooleanField()
mobile_application = models.NullBooleanField()
#
logo = models.ImageField(verbose_name='Logo', upload_to=logo_name, blank=True)
logo = models.ImageField(verbose_name='Logo', upload_to=logo_name, blank=True, max_length=255)
rating = models.IntegerField(default=0)
partner = models.NullBooleanField(default=0)
# delete after profiling
files = generic.GenericRelation('file.FileModel', content_type_field='content_type', object_id_field='object_id')
@ -255,7 +256,7 @@ class Hall(TranslatableModel):
Create Hall model which saves information about halls in PlaceExposition
"""
place_exposition = models.ForeignKey(PlaceExposition, related_name='halls')
number = models.PositiveIntegerField(blank=True, null=True)
number = models.CharField(blank=True, max_length=6)
capacity = models.PositiveIntegerField(blank=True, null=True)
translations = TranslatedFields(
name = models.CharField(max_length=255, blank=True)
@ -263,7 +264,42 @@ class Hall(TranslatableModel):
def calculate_rating(place):
rating_simple = {'address': 20, 'phone': 5, 'fax': 5, 'email': 5,
'web_page': 5, 'logo': 20, 'event_in_year': 5, 'total_area': 5, 'closed_area': 5,
'total_pavilions': 5, 'description':15, 'foundation_year': 5, 'total_halls': 5, 'virtual_tour': 5 }
rating_methods = {'theme': 10, 'tag': 5, 'photo':5}
# base rating
rating = 100
for key, value in rating_simple.iteritems():
if getattr(place, key):
rating += value
place.rating = rating
# call to prevent recursion
post_save.disconnect(create_place, sender=PlaceExposition)
place.save()
post_save.connect(create_place, sender=PlaceExposition)
def create_place(sender, instance, created, **kwargs):
post_save_handler(sender, instance=instance, **kwargs)
calculate_rating(instance)
#test
pre_save.connect(pre_save_handler, sender=PlaceExposition)
post_save.connect(post_save_handler, sender=PlaceExposition)
post_save.connect(post_save_handler, sender=Hall)
post_save.connect(create_place, sender=PlaceExposition)
post_save.connect(post_save_handler, sender=Hall)
"""
def calculate_rating_for_translations(sender, instance, created, **kwargs):
company = instance.master
post_save.disconnect(calculate_rating_for_translations, sender=Company._meta.translations_model)
calculate_rating(company)
post_save.connect(calculate_rating_for_translations, sender=Company._meta.translations_model)
post_save.connect(create_company, sender=Company)
post_save.connect(calculate_rating_for_translations, sender=Company._meta.translations_model)
"""

@ -9,18 +9,17 @@ urlpatterns = patterns('',
url(r'search/', PlaceSearchView.as_view()),
# correct
#url(r'country/$', PlaceCountryCatalog.as_view()),
url(r'country/(?P<slug>.*)/page/(?P<page>\d+)/$', PlaceCountryCatalog.as_view()),
url(r'country/(?P<slug>.*)/$', PlaceCountryCatalog.as_view()),
url(r'country/(?P<slug>.*)/page/(?P<page>\d+)/$', PlaceCountryCatalog.as_view(), {'meta_id':49}),
url(r'country/(?P<slug>.*)/$', PlaceCountryCatalog.as_view(), {'meta_id':49}),
# correct
#url(r'expo/city/$', ExpositionByCity.as_view()),
url(r'city/(?P<slug>.*)/page/(?P<page>\d+)/$', PlaceCityCatalog.as_view()),
url(r'city/(?P<slug>.*)/$', PlaceCityCatalog.as_view()),
url(r'city/(?P<slug>.*)/page/(?P<page>\d+)/$', PlaceCityCatalog.as_view(), {'meta_id':48}),
url(r'city/(?P<slug>.*)/$', PlaceCityCatalog.as_view(), {'meta_id':48}),
#!!!
url(r'(?P<slug>.*)/photo/page/(?P<page>\d+)/$', PlacePhoto.as_view()),
url(r'(?P<slug>.*)/photo/$', PlacePhoto.as_view()),
#url(r'expo/(?P<slug>.*)/service/(?P<url>.*)/$', ExpositionServiceView.as_view()),
url(r'(?P<slug>.*)/$', PlaceDetail.as_view()),
url(r'page/(?P<page>\d+)/$', PlaceList.as_view()),
url(r'$', PlaceList.as_view()),
url(r'page/(?P<page>\d+)/$', PlaceList.as_view(), {'meta_id':46}),
url(r'(?P<slug>.*)/$', PlaceDetail.as_view(), {'meta_id':47}),
url(r'$', PlaceList.as_view(), {'meta_id':46}),
)

@ -13,6 +13,10 @@ from place_conference.models import PlaceConference
from country.models import Country
from city.models import City
from models import PlaceExposition
from meta.views import MetadataMixin
from django.conf import settings
from functions.cache_mixin import JitterCacheMixin, CacheMixin
def catalog(request):
expo = list(PlaceExposition.objects.all())
@ -47,7 +51,8 @@ class PlaceSearchView(ExpoSearchView):
search_form = PlaceSearchForm
model = PlaceExposition
class PlaceDetail(DetailView):
class PlaceDetail(JitterCacheMixin, MetadataMixin, DetailView):
cache_range = settings.CACHE_RANGE
model = PlaceExposition
search_form = PlaceSearchForm
slug_field = 'url'
@ -97,7 +102,6 @@ class PlaceDetail(DetailView):
class PlacePhoto(ListView):
template_name = 'client/place/photo.html'
obj = None
search_form = PlaceSearchForm
def get_queryset(self):
slug = self.kwargs.get('slug')
@ -115,11 +119,10 @@ class PlacePhoto(ListView):
def get_context_data(self, **kwargs):
context = super(PlacePhoto, self).get_context_data(**kwargs)
context['object'] = self.obj
context['search_form'] = self.search_form
return context
class PlaceList(ListView):
class PlaceList(JitterCacheMixin, MetadataMixin, ListView):
model = PlaceExposition
paginate_by = 10
template_name = 'client/place/place_list.html'
@ -127,8 +130,8 @@ class PlaceList(ListView):
def get_queryset(self):
lang = translation.get_language()
qs = super(PlaceList, self).get_queryset().filter(language_code=lang)
#qs = super(PlaceList, self).get_queryset().order_by('-rating')
qs= PlaceExposition.objects.language().select_related('country', 'city').all().order_by('-rating')
conf_qs = PlaceConference.objects.language().all()
return list(qs)+list(conf_qs)
@ -138,17 +141,16 @@ class PlaceList(ListView):
return context
class PlaceCatalog(ListView):
class PlaceCatalog(JitterCacheMixin, MetadataMixin, ListView):
cache_range = settings.CACHE_RANGE
model = PlaceExposition
paginate_by = 10
template_name = 'place/catalog.html'
search_form = PlaceSearchForm
template_name = 'client/place/catalog.html'
filter_object = None
def get_context_data(self, **kwargs):
context = super(PlaceCatalog, self).get_context_data(**kwargs)
context['search_form'] = self.search_form
context['filter_object'] = self.filter_object
context['catalog_url'] = self.catalog_url
@ -161,9 +163,10 @@ class PlaceCountryCatalog(PlaceCatalog):
def get_queryset(self):
slug = self.kwargs.get('slug')
country = get_object_or_404(Country, url=slug)
self.kwargs['country'] = country
self.filter_object = country
qs = self.model.objects.language().filter(country=country).order_by('-rating')
conf_qs = PlaceConference.objects.language().filter(country=country)
qs = self.model.objects.language().select_related('country', 'city').filter(country=country).order_by('-rating')
conf_qs = PlaceConference.objects.language().select_related('country', 'city').filter(country=country)
return list(qs) + list(conf_qs)
@ -174,7 +177,8 @@ class PlaceCityCatalog(PlaceCatalog):
def get_queryset(self):
slug = self.kwargs.get('slug')
city = get_object_or_404(City, url=slug)
self.kwargs['city'] = city
self.filter_object = city
qs = self.model.objects.language().filter(city=city).order_by('-rating')
conf_qs = PlaceConference.objects.language().filter(city=city)
qs = self.model.objects.language().select_related('country', 'city').filter(city=city).order_by('-rating')
conf_qs = PlaceConference.objects.language().select_related('country', 'city').filter(city=city)
return list(qs) + list(conf_qs)

@ -9,9 +9,11 @@ from file.models import TmpFile, FileModel
from file.forms import FileModelForm, FileForm
from city.models import City
from theme.models import Tag
from article.models import Article
from django.db.models.loading import get_model
def admin_home(request):
return render_to_response('base.html')
@ -39,6 +41,24 @@ def ajax_tag(request):
else:
#request empty - send empty array
return HttpResponse('[]', content_type='application/json')
def get_news(request):
"""
return array of tags (id, name) filtered by theme values from request
"""
term = request.GET['term'].capitalize()
if not term:
qs = Article.objects.news()[:50]
else:
qs = Article.objects.news().filter(translations__main_title__contains=term)
result = [{'id': item.id, 'label': item.main_title} for item in qs]
return HttpResponse(json.dumps(result), content_type='application/json')
'''
def ajax_post_file(request, obj_id=None):
"""
@ -159,6 +179,38 @@ def ajax_post_timetable(request, obj_id=None):
else:
return HttpResponse('error')
from exposition.models import Statistic
from exposition.forms import StatisticForm
def ajax_post_stat(request, obj_id=None):
response = {'success': False}
if request.GET:
form = StatisticForm(request.GET)
if form.is_valid():
exp = Exposition.objects.safe_get(id=obj_id)
if exp:
form.save(exp)
response['success'] = True
else:
response.update({'errors': form.errors})
return HttpResponse(json.dumps(response), content_type='application/json')
def ajax_delete_stat(request, id):
redirect_to = request.META.get('HTTP_REFERER')
if id:
try:
Statistic.objects.get(id=id).delete()
except Statistic.DoesNotExist:
pass
return HttpResponseRedirect(redirect_to)
def ajax_delete_timetable(request):
if request.GET:

@ -29,6 +29,7 @@ urlpatterns = required(
url(r'^translator/', include('translator.admin_urls')),
url(r'^webinar/', include('webinar.admin_urls')),
url(r'^settings/', include('settings.admin_urls')),
url(r'^meta/', include('meta.admin_urls')),
url(r'^language/add/', 'directories.admin.language_add'),
url(r'^currency/add/', 'directories.admin.currency_add'),
# ajax requests
@ -36,6 +37,8 @@ urlpatterns = required(
url(r'^ajax_post_file/', 'proj.admin.ajax_post_file'),
url(r'^ajax_post_photo/(?P<obj_id>\d+)/$', 'proj.admin.ajax_post_photo'),#must be before /ajax_post_photo/
url(r'^ajax_post_photo/', 'proj.admin.ajax_post_photo'),
url(r'^ajax_post_stat/(?P<obj_id>\d+)/$', 'proj.admin.ajax_post_stat'),
url(r'^ajax_delete_stat/(?P<id>\d+)/', 'proj.admin.ajax_delete_stat'),
url(r'^ajax_post_timetable/(?P<obj_id>\d+)/$', 'proj.admin.ajax_post_timetable'),#must be before /ajax_post_timetable/
url(r'^ajax_post_timetable/', 'proj.admin.ajax_post_timetable'),
url(r'^ajax_delete_timetable/', 'proj.admin.ajax_delete_timetable'),
@ -43,6 +46,7 @@ urlpatterns = required(
url(r'^ajax_delete_file/', 'proj.admin.ajax_delete_file'),
url(r'^ajax_city/', 'proj.admin.ajax_city'),
url(r'^ajax_tag/', 'proj.admin.ajax_tag'),
url(r'^ajax/get-news/', 'proj.admin.get_news'),
#
url(r'^ckeditor/', include('ckeditor.urls')),
url(r'^tinymce/', include('tinymce.urls')),

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# Django local settings
DEBUG = True # изменить когда будет продакшн
DEBUG = False
ALLOWED_HOSTS = ['hit.expomap.ru', '195.66.79.152', '195.66.79.145', 'expomap.ru']
DATABASES = {
'default': {

@ -22,23 +22,27 @@ DATABASES = {
'NAME': 'test2',
'USER': 'kotzilla',
'PASSWORD': 'qazedc',
'HOST': '',
'HOST': '195.66.79.152',
'PORT': '',
}
}
'''
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
"default": {
"BACKEND": "redis_cache.cache.RedisCache",
"LOCATION": "127.0.0.1:6379:1",
"OPTIONS": {
"CLIENT_CLASS": "redis_cache.client.DefaultClient",
},
}
}
'''
# Hosts/domain names that are valid for this site; required if DEBUG is False
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['hit.expomap.ru', '195.66.79.152', '195.66.79.145', 'expomap.ru']
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
@ -71,15 +75,14 @@ USE_I18N = True
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True
USE_L10N = False
# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True
USE_TZ = False
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/var/www/example.com/media/"
MEDIA_ROOT = os.path.join(SITE_ROOT, 'media/')#'/home/kotzilla/Documents/qwer/proj/media/'
CKEDITOR_UPLOAD_PATH = os.path.join(SITE_ROOT, 'media/upload')#'/home/kotzilla/Documents/qwer/proj/media/upload'
MEDIA_ROOT = os.path.join(SITE_ROOT, 'media/')
CKEDITOR_UPLOAD_PATH = os.path.join(SITE_ROOT, 'media/upload')
CKEDITOR_CONFIGS = {
@ -95,37 +98,13 @@ CKEDITOR_CONFIGS = {
},
}
#TINYMCE_JS_URL = os.path.join(MEDIA_ROOT, "js/tiny_mce/tiny_mce.js")
#TINYMCE_DEFAULT_CONFIG = {
# 'plugins': "table,spellchecker,paste,searchreplace",
# 'theme': "advanced",
# 'cleanup_on_startup': True,
# 'custom_undo_redo_levels': 10,
# 'width' : 565,
# 'height' : 100
#}
#TINYMCE_SPELLCHECKER = True
#TINYMCE_COMPRESSOR = True
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://example.com/media/", "http://media.example.com/"
MEDIA_URL = '/media/'
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/var/www/example.com/static/"
STATIC_ROOT = os.path.join(SITE_ROOT, 'static')
# URL prefix for static files.
# Example: "http://example.com/static/", "http://static.example.com/"
STATIC_URL = '/static/'
# Additional locations of static files
# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
@ -135,7 +114,7 @@ STATICFILES_FINDERS = (
# Make this unique, and don't share it with anybody.
SECRET_KEY = '=yz1@ko%1s8bmel)c84#s*xpxn%4(1e+smdnh*@rdm*5%v!mln'
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
@ -160,8 +139,6 @@ TEMPLATE_CONTEXT_PROCESSORS = (
MIDDLEWARE_CLASSES = (
# 'django.middleware.cache.UpdateCacheMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
@ -173,7 +150,6 @@ MIDDLEWARE_CLASSES = (
# Uncomment the next line for simple clickjacking protection:
'django.middleware.clickjacking.XFrameOptionsMiddleware',
#'debug_toolbar.middleware.DebugToolbarMiddleware',
)
@ -187,7 +163,7 @@ TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(SITE_ROOT, 'templates'),
# os.path.join(SITE_ROOT, 'templates/debug_toolbar'),
os.path.join(SITE_ROOT, 'templates/admin'),
os.path.join(SITE_ROOT, 'templates/admin/accounts'),
os.path.join(SITE_ROOT, 'templates/admin/article'),
@ -215,6 +191,7 @@ TEMPLATE_DIRS = (
os.path.join(SITE_ROOT, 'templates/client/exposition'),
os.path.join(SITE_ROOT, 'templates/client/photoreport'),
os.path.join(SITE_ROOT, 'templates/client/includes'),
os.path.join(SITE_ROOT, 'templates'),
#os.path.join(SITE_ROOT, 'templates/client/popups'),
)
@ -223,16 +200,13 @@ LOGIN_URL='/'
#registration info
ACCOUNT_ACTIVATION_DAYS=2
# mail settings
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
#EMAIL_HOST = 'localhost'
#EMAIL_HOST_USER = 'kotzilla'
EMAIL_HOST_USER = 'kotzillla@gmail.com'
EMAIL_HOST_PASSWORD = 'fitteR2006!'
EMAIL_PORT = 587
#DEFAULT_FROM_EMAIL = 'kotzillla@gmail.com'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
EMAIL_PORT = 25
DEFAULT_FROM_EMAIL = "expomap.ru"
AUTHENTICATION_BACKENDS = (
@ -303,6 +277,7 @@ INSTALLED_APPS = (
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'django.contrib.sitemaps',
'haystack',
#custom modules
'accounts',
@ -330,32 +305,27 @@ INSTALLED_APPS = (
'translator',
'webinar',
'meta',
'banners',
#django modules
'sorl.thumbnail',
'photologue',
'sortedm2m',
'hvad',
'tinymce',
'ckeditor',
'django_messages',
'sorl.thumbnail', # for logos
'photologue', # photogallery
'sortedm2m', # photologue dependence
'hvad', #
'tinymce', # ???
'ckeditor', # wysiwig editor in admin
'django_messages', # messages
'bitfield',
'djutils',
'pytils',
'pymorphy',
'password_reset',
#'social_auth',
'social.apps.django_app.default',
# 'south',
#'debug_toolbar',
'djutils', # ??
'pytils', # ??
'pymorphy', # ??
'password_reset', # reset password
'django_crontab', # crons
'social.apps.django_app.default', # social auth
)
INTERNAL_IPS = ('176.121.5.82',)
DEBUG_TOOLBAR_PATCH_SETTINGS = False
#DEBUG_TOOLBAR_PANELS = (
# 'debug_toolbar.panels.profiling.ProfilingPanel',
#)
PYMORPHY_DICTS = {
'ru': { 'dir': '/home/www/proj/settings/russian_dicts' },
'ru': { 'dir': os.path.join(SITE_ROOT, 'settings/russian_dicts')} #'/home/www/proj/settings/russian_dicts' },
}
# search backend
@ -398,18 +368,82 @@ LOGGING = {
}
}
THUMBNAIL_DEBUG = True
CRONJOBS = [
('0 */1 * * *', 'django.core.management.call_command', ['update_index conference --age=1']),
('0 */1 * * *', 'django.core.management.call_command', ['update_index exposition --age=1']),
('0 */12 * * *', 'django.core.management.call_command', ['update_index place_exposition --age=12']),
('0 */24 * * *', 'django.core.management.call_command', ['update_index company --age=24']),
('0 */24 * * *', 'django.core.management.call_command', ['update_index theme --age=24']),
('0 */24 * * *', 'django.core.management.call_command', ['update_index tag --age=24']),
]
THUMBNAIL_DEBUG = DEBUG
CALLBACK_EMAIL = 'kotzilla@ukr.net'
BOOKING_AID = '333667'
"""
ADMIN_PAGINATION = 20
CLIENT_PAGINATION = 15
TEMPLATE_DEBUG = DEBUG
NO_LOGO = '/static/client/img/no-logo.png'
# events settings
CURRENCY = ('RUB', 'USD', 'EUR', 'RMB', 'GBP', 'AED', 'SGD', 'TRY', 'CZK', 'CHF', 'SEK', 'LKR', 'UAH', 'IDR', 'PLN','JPY')
BIT_AUDIENCE = (('experts', _(u'Специалисты')), ('experts and consumers', _(u'Специалисты и потребители')),
('general public', _(u'Широкая публика')))
MONTHES = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2, 'name': _(u'Февраль')},
'mar': {'value': 3, 'name': _(u'Март')}, 'apr': {'value': 4, 'name': _(u'Апрель')},
'may': {'value': 5, 'name': _(u'Май')}, 'jun': {'value': 6, 'name': _(u'Июнь')},
'jul': {'value': 7, 'name': _(u'Июль')}, 'aug': {'value': 8, 'name': _(u'Август')},
'sep': {'value': 9, 'name': _(u'Сентябрь')}, 'oct': {'value': 10, 'name': _(u'Октябрь')},
'nov': {'value': 11, 'name': _(u'Ноябрь')}, 'dec': {'value': 12, 'name': _(u'Декабрь')}}
SNG_COUNTRIES = [159, 186, 31, 6, 99, 13, 189, 64]
# cache pages in random seconds. random in this range
CACHE_RANGE = [60, 120]
try:
from local import *
except ImportError, e:
from production import *
pass
# debug_toolbar settings
"""
ADMIN_PAGINATION = 20
CLIENT_PAGINATION = 15
TEMPLATE_DEBUG = DEBUG
if DEBUG:
DEBUG_TOOLBAR_PATCH_SETTINGS = False
INTERNAL_IPS = ('127.0.0.1','176.121.5.82', '176.121.11.162', '77.123.47.46')
MIDDLEWARE_CLASSES += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
INSTALLED_APPS += (
'debug_toolbar',
)
JQUERY_URL = os.path.join(SITE_ROOT, 'static/client/js/jquery-ui-1.10.4.custom.min.js'),
DEBUG_TOOLBAR_PANELS = [
#'debug_toolbar.panels.versions.VersionsPanel',
#'debug_toolbar.panels.timer.TimerPanel',
#'debug_toolbar.panels.settings.SettingsPanel',
#'debug_toolbar.panels.headers.HeadersPanel',
#'debug_toolbar.panels.request.RequestPanel',
'debug_toolbar.panels.sql.SQLPanel',
#'debug_toolbar.panels.staticfiles.StaticFilesPanel',
#'debug_toolbar.panels.templates.TemplatesPanel',
#'debug_toolbar.panels.cache.CachePanel',
#'debug_toolbar.panels.signals.SignalsPanel',
#'debug_toolbar.panels.logging.LoggingPanel',
#'debug_toolbar.panels.redirects.RedirectsPanel',
]
#DEBUG_TOOLBAR_CONFIG = {
# 'INTERCEPT_REDIRECTS': False,
#}
"""

@ -0,0 +1,141 @@
import datetime
from django.contrib.sitemaps import Sitemap
from exposition.models import Exposition
from conference.models import Conference
from city.models import City
from country.models import Country
from theme.models import Theme, Tag
from article.models import Article
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator
class Abstract(Sitemap):
changefreq = 'weekly'
priority = 0.8
def lastmod(self, obj):
return datetime.date.today()
class ExpoCard(Abstract):
changefreq = 'weekly'
priority = 0.8
def items(self):
return Exposition.enable.upcoming()
def lastmod(self, obj):
return obj.modified
class ExpoCity(Abstract):
def items(self):
return City.used.expo_cities()
def location(self, obj):
return "/expo/city/%s/" % obj.url
class ExpoCountry(Abstract):
def items(self):
return Country.objects.expo_countries()
def location(self, obj):
return "/expo/country/%s/" % obj.url
class ExpoTheme(Abstract):
def items(self):
return Theme.active.expo_themes()
def location(self, obj):
return "/expo/theme/%s/" % obj.url
class ExpoTag(Abstract):
def items(self):
return Tag.active.expo_tag()
def location(self, obj):
return "/expo/tag/%s/" % obj.url
class ConfCard(Sitemap):
changefreq = 'weekly'
priority = 0.8
def items(self):
return Conference.enable.upcoming()
def lastmod(self, obj):
return obj.modified
def location(self, obj):
return "/conference/%s/" % obj.url
class ConfCity(Abstract):
def items(self):
return City.used.conference_cities()
def location(self, obj):
return "/conference/city/%s/" % obj.url
class ConfCountry(Abstract):
def items(self):
return Country.objects.conference_countries()
def location(self, obj):
return "/conference/country/%s/" % obj.url
class ConfTheme(Abstract):
def items(self):
return Theme.active.conference_themes_with_count()
def location(self, obj):
return "/conference/theme/%s/" % obj.url
class ConfTag(Abstract):
def items(self):
return Tag.active.conference_tags()
def location(self, obj):
return "/conference/tag/%s/" % obj.url
class NewsSiteMap(Abstract):
priority = 0.5
def items(self):
return Article.objects.news().filter(publish_date__isnull=False)
def location(self, obj):
return "/news/%s/" % obj.slug
class BlogsSiteMap(Abstract):
priority = 0.5
def items(self):
return Article.objects.blogs().filter(publish_date__isnull=False)
def location(self, obj):
return "/blogs/%s/" % obj.slug
class SimpleAbstract(Sitemap):
priority = 0.5
def location(self, item):
return item
class Important(SimpleAbstract):
priority = 1
def items(self):
return ['', '/expo/', '/conference/', '/conference/country/', '/conference/city/', '/conference/theme/',
'/expo/theme/', '/expo/country/', '/expo/city/']
class Additional(SimpleAbstract):
priority = 0.5
def items(self):
return ['/blogs/', '/news/', '/partners/', '/about/', '/advertising/', '/contacts/']

@ -1,23 +1,44 @@
# -*- coding: utf-8 -*-
from django.conf import settings
from django.conf.urls import patterns, include, url
from core.views import PlaceListView, PlacePhotoView, EventSearchView
from core.simple_index_view import AdvertisingView, AboutView
from views import MainPageView, MainPageViewTest
from place_exposition.views import PlaceSearchView
from views import MainPageView
from django.contrib.sitemaps import views
import debug_toolbar
from django.views.generic.base import TemplateView
from django.http import HttpResponse
class Robot(TemplateView):
template_name = 'robots.txt'
content_type = 'text/plain'
from django.contrib.sitemaps import Sitemap
from exposition.models import Exposition
from sitemaps import ExpoCard, ExpoCity, ExpoCountry, ExpoTheme, ExpoTag, ConfCard, ConfCity, ConfCountry, ConfTheme,\
ConfTag, NewsSiteMap, BlogsSiteMap, Additional, Important
sitemaps = {
'expo_card': ExpoCard(), 'news': NewsSiteMap(), 'blogs': BlogsSiteMap(), 'expo_city': ExpoCity(), \
'expo_country': ExpoCountry(), 'expo_theme': ExpoTheme(), \
'conference_card': ConfCard(), 'expo_tag': ExpoTag(), 'conference_city': ConfCity(), 'conference_country': ConfCountry(),\
'conference_theme': ConfTheme(), 'conference_tag': ConfTag(), 'main': Important(), 'additional': Additional()
}
urlpatterns = patterns('',
#url(r'^__debug__/', include(debug_toolbar.urls)),
url(r'^admin/', include('proj.admin_urls')),
#url(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
url(r'^sitemap\.xml$', views.index, {'sitemaps': sitemaps}),
url(r'^sitemap-(?P<section>.+)\.xml$', views.sitemap, {'sitemaps': sitemaps}),
url(r'^robots.txt$', Robot.as_view()),
url(r'^$', MainPageView.as_view()),
url(r'^main_page/$', MainPageViewTest.as_view()),
url(r'^theme/', include('theme.urls')),
url(r'^places/', include('place_exposition.urls')),
url(r'^', include('accounts.urls')),
url(r'^', include('exposition.urls')),
url(r'^', include('settings.conference_old_urls')), # conference redirects from old version
url(r'^', include('conference.urls')),
url(r'^', include('seminar.urls')),
url(r'^', include('webinar.urls')),
@ -28,47 +49,30 @@ urlpatterns = patterns('',
url(r'^city/', include('city.urls')),
url(r'^organiser/', include('organiser.urls')),
url(r'^gallery/', include('photologue.client_urls')),
url(r'^', include('file.urls')),
url(r'^', include('django_messages.expomap_urls')),
url(r'^messages/', include('django_messages.urls')),
url(r'^advertising/$', AdvertisingView.as_view()),
url(r'^about/$', AboutView.as_view()),
url(r'^partners/$', AboutView.as_view()),
url(r'^contacts/$', AboutView.as_view()),
#url(r'^events/search/$', EventSearchView.as_view()),
#url(r'^places/search/$', PlaceSearchView.as_view()),
#url(r'^places/(?P<params>.*)/photo/(?P<page>\d+)/$', PlacePhotoView.as_view()),
#url(r'^places/(?P<params>.*)/photo/$', PlacePhotoView.as_view()),
#url(r'^places/(?P<params>.*)/(?P<page>\d+)/$', PlaceListView.as_view()),
#url(r'^places/(?P<page>\d+)/$', PlaceListView.as_view()),
#url(r'^places/(?P<params>.*)/$', PlaceListView.as_view()),
#url(r'^places/$', PlaceListView.as_view()),
url(r'^advertising/$', AdvertisingView.as_view(), {'meta_id':58}),
url(r'^about/$', AboutView.as_view(), {'meta_id':56}),
url(r'^partners/$', AboutView.as_view(), {'meta_id':57}),
url(r'^contacts/$', AboutView.as_view(), {'meta_id':59}),
url(r'^social/', include('social.apps.django_app.urls', namespace='social')),
url(r'^login/', 'registration.backends.default.views.LoginView'),
url(r'^logout/', 'registration.backends.default.views.LogoutView'),
#url(r'^profile/$', 'accounts.views.profile'),
url(r'^accounts/', include('registration.backends.default.urls')),
#url(r'^places/$', 'place_exposition.views.catalog'),
#url(r'^places/(?P<url>.*)/(?P<photo>photo)', 'place_exposition.views.place'),
#url(r'^places/(?P<url>.*)', 'place_exposition.views.place'),
#url(r'^company/(?P<url>.*)', 'core.views.company'),
url(r'^', include('password_reset.urls')),
url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^redirect/', include('banners.urls')),
#url(r'^social/', include('social_auth.urls')),
# admin part
url(r'^search/', include('haystack.urls')),
url(r'^', include('settings.old_urls')),
#url(r'^search/', include('haystack.urls')),
url(r'^', include('service.urls')),
)
# ajax urls
urlpatterns += patterns('',
url(r'^registration/reply/$', 'registration.backends.default.views.RegisterReply'),
url(r'^register/', 'registration.backends.default.views.RegisterAjaxView'),
url(r'^register-complete/', 'registration.backends.default.views.complete_registration'),
url(r'^callback/', 'core.simple_index_view.callback'),
@ -78,17 +82,13 @@ urlpatterns += patterns('',
url(r'^search-form/autosearch/exposition/$', 'settings.views.expo_autosearch'),
url(r'^search-form/autosearch/place/$', 'settings.views.place_autosearch'),
url(r'^search-form/autosearch/company/$', 'settings.views.company_autosearch'),
url(r'^', include('settings.old_urls')),
url(r'^', include('accounts.user_catalog_urls')),
)
"""
if settings.DEBUG:
import debug_toolbar
urlpatterns += patterns('',
url(r'^__debug__/', include(debug_toolbar.urls)),
)
"""
)

@ -8,6 +8,7 @@ from exposition.models import Exposition
from theme.models import Theme
from news.models import News
from article.models import Article
from functions.cache_mixin import JitterCacheMixin, CacheMixin
from functions.forms import ThemeSearch, PlaceSearch
@ -16,62 +17,37 @@ from functions.custom_views import ExpoListView
from accounts.forms import RegistrationCompleteForm
def expo_context(request):
cont = {'theme_search_form': ThemeSearch(), 'search_form': ExpositionSearchForm(), 'expo_catalog': Exposition.catalog,
'book_aid': settings.BOOKING_AID}
cont = {'theme_search_form': ThemeSearch(), 'expo_catalog': Exposition.catalog,
'book_aid': settings.BOOKING_AID, 'blogs': Article.objects.main_page_blogs(),
'news_list': Article.objects.main_page_news(), 'sng_countries': settings.SNG_COUNTRIES
}
user = request.user
if not user.is_anonymous() and not user.url:
cont.update({'reg_complete': RegistrationCompleteForm(instance=user)})
if not request.GET:
cont.update({'search_form': ExpositionSearchForm()})
return cont
class MainPageView(TemplateView):
class MainPageView(JitterCacheMixin,TemplateView):
cache_range = settings.CACHE_RANGE
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super(MainPageView, self).get_context_data(**kwargs)
events = Exposition.objects.all().order_by('-main_page')[:5]
exposition_themes = Theme.objects.order_by('-main_page').filter(types=Theme.types.exposition)[:6]
conference_themes = Theme.objects.order_by('-main_page').filter(types=Theme.types.conference)[:6]
seminar_themes = Theme.objects.order_by('-main_page').filter(types=Theme.types.seminar)[:6]
news_list = News.objects.order_by('-main_page').all()[:3]
articles = Article.objects.order_by('-main_page').all()[:2]
args = {'events': events, 'exposition_themes': exposition_themes,
'conference_themes': conference_themes, 'seminar_themes': seminar_themes,
'news_list': news_list, 'articles': articles, 'search_form': EventSearchForm,
'search_action': '/events/search/'}
events = Exposition.objects.language().select_related('country', 'city', 'place').filter(main_page=1)
exposition_themes = Theme.objects.language().order_by('-main_page').filter(types=Theme.types.exposition)[:6]
conference_themes = Theme.objects.language().order_by('-main_page').filter(types=Theme.types.conference)[:6]
args = {'events': events, 'exposition_themes': exposition_themes, 'conference_themes': conference_themes,
'search_form': ExpositionSearchForm, 'search_action': '/expo/search/'}
context.update(args)
return context
class MainPageViewTest(TemplateView):
template_name = 'client/main_page.html'
def get_context_data(self, **kwargs):
context = super(MainPageViewTest, self).get_context_data(**kwargs)
events = Exposition.objects.all().order_by('-main_page')[:5]
exposition_themes = Theme.objects.order_by('-main_page').filter(types=Theme.types.exposition)[:6]
conference_themes = Theme.objects.order_by('-main_page').filter(types=Theme.types.conference)[:6]
seminar_themes = Theme.objects.order_by('-main_page').filter(types=Theme.types.seminar)[:6]
news_list = News.objects.order_by('-main_page').all()[:3]
articles = Article.objects.order_by('-main_page').all()[:2]
args = {'events': events, 'exposition_themes': exposition_themes,
'conference_themes': conference_themes, 'seminar_themes': seminar_themes,
'news_list': news_list, 'articles': articles}
context.update(args)
return context
class AdvertisingView(TemplateView):
template_name = 'simple_pages/advertising.html'

@ -2,6 +2,7 @@
from django.conf import settings
from django.contrib.sites.models import RequestSite
from django.contrib.sites.models import Site
from django.utils.translation import ugettext as _
from registration import signals
from registration.models import RegistrationProfile
@ -34,7 +35,7 @@ class RegistrationView(BaseRegistrationView):
* The creation of the templates
``registration/activation_email_subject.txt`` and
``registration/activation_email.txt``, which will be used for
``registration/activation_email.html``, which will be used for
the activation email. See the notes for this backends
``register`` method for details regarding these templates.
@ -187,6 +188,35 @@ def RegisterAjaxView(request):
# 404
# return HttpResponse('not ajax')
def RegisterReply(request):
if request.GET:
email = request.GET['email']
try:
user = User.objects.get(username=email)
except User.DoesNotExist:
response = {'errors': {'email': _(u'Пользователя с таким email не существует')}}
return HttpResponse(json.dumps(response), content_type='application/json')
if user.is_active:
response = {'errors': {'email': _(u'Пользователя с таким email уже активирован')}}
return HttpResponse(json.dumps(response), content_type='application/json')
else:
try:
registration_profile = user.registrationprofile_set.all()[0]
except IndexError:
registration_profile = RegistrationProfile.create_profile(user)
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
registration_profile.send_activation_email(site)
response = {'success': True}
return HttpResponse(json.dumps(response), content_type='application/json')
else:
return HttpResponse('no data')
from django.contrib.auth.forms import AuthenticationForm
from registration.forms import LoginForm
@ -199,7 +229,7 @@ def LogoutView(request):
def LoginView(request):
if request.POST:
form = AuthenticationForm(data=request.POST)
form = LoginForm(data=request.POST)
#return HttpResponse(form.username)
@ -210,6 +240,8 @@ def LoginView(request):
#return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
else:
response={'success':False, 'errors': form.errors}
if getattr(form, 'inactive', None):
response.update({'inactive': True})
return HttpResponse(json.dumps(response), content_type='application/json')
@ -222,8 +254,9 @@ def complete_registration(request):
response = {'success': False}
form = RegistrationCompleteForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
user = form.save()
response['success']=True
response['redirect'] = user.get_permanent_url()
else:
response['errors'] = form.errors
return HttpResponse(json.dumps(response), content_type='application/json')

@ -127,6 +127,33 @@ class RegistrationFormNoFreeEmail(RegistrationForm):
raise forms.ValidationError(_("Registration using free email addresses is prohibited. Please supply a different email address."))
return self.cleaned_data['email']
from django.contrib.auth import authenticate
class LoginForm(AuthenticationForm):
username = forms.CharField(max_length=254, widget=forms.TextInput(attrs={'placeholder': _(u'Ваш адрес электронной почты')}))
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput(attrs={'placeholder': _(u'Ваш Пароль')}))
inactive = False
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
data = self.cleaned_data
if username and password:
self.user_cache = authenticate(username=username,
password=password)
if self.user_cache is None:
self._errors['password'] = ErrorList([self.error_messages['invalid_login'] % {
'username': self.username_field.verbose_name
}])
del data['password']
elif not self.user_cache.is_active:
self._errors['username'] = ErrorList([self.error_messages['inactive']])
self.inactive = True
del data['username']
self.check_for_test_cookie()
return data

@ -2,13 +2,15 @@ import datetime
import hashlib
import random
import re
from django.core.mail import EmailMessage
from django.conf import settings
from django.contrib.auth.models import User
from django.db import models
from django.db import transaction
from django.template.loader import render_to_string
from django.template.loader import render_to_string, get_template
from django.template import Context
from django.utils.translation import ugettext_lazy as _
from email.MIMEImage import MIMEImage
try:
from django.contrib.auth import get_user_model
@ -232,7 +234,7 @@ class RegistrationProfile(models.Model):
text; output longer than one line will be forcibly joined
into only a single line.
``registration/activation_email.txt``
``registration/activation_email.html``
This template will be used for the body of the email.
These templates will each receive the following context
@ -256,15 +258,33 @@ class RegistrationProfile(models.Model):
framework for details regarding these objects' interfaces.
"""
user = self.user
ctx_dict = {'activation_key': self.activation_key,
'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
'site': site}
'site': site,
'user': user}
subject = render_to_string('registration/activation_email_subject.txt',
ctx_dict)
# Email subject *must not* contain newlines
subject = ''.join(subject.splitlines())
message = get_template('registration/activation_email.html').render(Context(ctx_dict))
msg = EmailMessage(subject, message, settings.DEFAULT_FROM_EMAIL, [user.email])
msg.content_subtype = "html"
images =(('/img/logo_reg.png', 'logo'),
('/img/soc-medias/sm-icon-rss.png', 'rss'),
('/img/soc-medias/sm-icon-fb.png', 'fb'),
('/img/soc-medias/sm-icon-lin.png', 'linkedin'),
('/img/soc-medias/sm-icon-vk.png', 'vk'),
('/img/soc-medias/sm-icon-twit.png', 'twit'),
('/img/mail-logo-2.jpg','logo2'))
for img in images:
fp = open(settings.STATIC_ROOT+img[0], 'rb')
msg_img = MIMEImage(fp.read())
fp.close()
msg_img.add_header('Content-ID', '<'+img[1]+'>')
msg.attach(msg_img)
msg.send()
message = render_to_string('registration/activation_email.txt',
ctx_dict)
self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
#self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)

@ -28,16 +28,15 @@ class ServiceForm(forms.Form):
url = forms.CharField(label='url', required=False)
price = forms.IntegerField(label='Цена', required=False,
widget=forms.TextInput(attrs={'placeholder':'Валюта'}))
#price = forms.CharField(label='Цена', required=False,
# widget=forms.TextInput(attrs={'placeholder':'Валюта'}))
currency_list = [('USD','USD'), ('EUR','EUR'), ('RUB','RUB')]
currency = forms.ChoiceField(choices=currency_list)
type = forms.MultipleChoiceField(label='Тип', choices=[('expo', 'expo'), ('conference', 'conference')])
service_id = forms.CharField(required=False, widget=forms.HiddenInput())
def __init__(self, *args, **kwargs):
super(ServiceForm, self).__init__(*args, **kwargs)
# creates translated form fields, example: name_ru, name_en
@ -76,6 +75,8 @@ class ServiceForm(forms.Form):
service.price = data['price']
service.currency = data['currency']
#data['type']
fill_with_signal(Service, service, data)

@ -2,9 +2,10 @@
from django.db import models
from hvad.models import TranslatableModel, TranslatedFields, TranslationManager
from functions.custom_fields import EnumField
from bitfield import BitField
CURENCIES = ('USD', 'RUB', 'EUR')
CURENCIES = ('', 'USD', 'RUB', 'EUR')
@ -12,12 +13,12 @@ CURENCIES = ('USD', 'RUB', 'EUR')
class Service(TranslatableModel):
url = models.SlugField(unique=True)
currency = EnumField(values=CURENCIES, blank=True, default='USD')
price = models.PositiveIntegerField(blank=True, null=True)
params = models.CharField(max_length=255, blank=True)
template = models.CharField(max_length=255, blank=True)
type = BitField(flags=['expo', 'conference'])
#translated fields
translations = TranslatedFields(
name = models.CharField(max_length=50),
@ -31,6 +32,7 @@ class Service(TranslatableModel):
)
sort = models.PositiveIntegerField(default=0, db_index=True)
main_page = models.PositiveIntegerField(default=0, db_index=True)
meta_id = models.IntegerField(null=True)
def __unicode__(self):
@ -65,15 +67,20 @@ class AbstractOrder(models.Model):
exposition = models.ForeignKey('exposition.Exposition', null=True)
conference = models.ForeignKey('conference.Conference', null=True)
seminar = models.ForeignKey('seminar.Seminar', null=True)
created = models.DateTimeField(auto_now_add=True)
viewed = models.DateTimeField(null=True, blank=True)
class Meta:
abstract = True
ordering = ['-created']
class Catalog(AbstractOrder):
pass
class BuildStand(AbstractOrder):
pass
class Tickets(AbstractOrder):
days = models.SmallIntegerField()
@ -81,7 +88,7 @@ class Tickets(AbstractOrder):
class Remote(AbstractOrder):
interested_participants = models.TextField(blank=True)
additional = models.CharField(max_length=255)
additional = models.CharField(max_length=255, blank=True)
class Participation(AbstractOrder):
@ -90,12 +97,12 @@ class Participation(AbstractOrder):
company_inf = models.TextField()
class Translation(AbstractOrder):
days = models.IntegerField()
hours = models.IntegerField()
fr = models.DateField()
to = models.DateField()
languages = models.TextField()
themes = models.TextField()
days = models.IntegerField(null=True,blank=True)
hours = models.IntegerField(null=True, blank=True)
fr = models.DateField(blank=True)
to = models.DateField(blank=True)
languages = models.TextField(blank=True)
themes = models.TextField(blank=True)
class Visit(AbstractOrder):
fr = models.DateField()
@ -122,3 +129,15 @@ class Visit(AbstractOrder):
excursion = models.BooleanField()
notes = models.TextField(blank=True)
class Advertising(AbstractOrder):
pass
class CallBack(models.Model):
phone = models.CharField(max_length=30)
person_inf = models.CharField(max_length=255)
created = models.DateTimeField(auto_now_add=True)
viewed = models.DateTimeField(null=True, blank=True)
class Meta:
ordering = ['-created']

@ -2,7 +2,7 @@
from django import forms
from django.utils.translation import ugettext as _
from accounts.models import User
from models import Catalog, Tickets, Remote, Participation, Translation, Visit, CURENCIES
from models import Catalog, Tickets, Remote, Participation, Translation, Visit, CURENCIES, Advertising, CallBack, BuildStand
from exposition.models import Exposition
from conference.models import Conference
from seminar.models import Seminar
@ -15,7 +15,7 @@ class AbstractOrderForm(forms.ModelForm):
phone = forms.CharField(widget=forms.TextInput(attrs={'placeholder': _(u'Контактный номер телефона')}))
person = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': _(u'Электронная почта')}))
currency = forms.CharField(widget=forms.HiddenInput())
currency = forms.CharField(widget=forms.HiddenInput(), required=False)
exposition = forms.CharField(widget=forms.HiddenInput(), required=False)
conference = forms.CharField(widget=forms.HiddenInput(), required=False)
@ -89,6 +89,10 @@ class CatalogForm(AbstractOrderForm):
class Meta:
model = Catalog
class BuildStandForm(AbstractOrderForm):
class Meta:
model = BuildStand
class TicketsForm(AbstractOrderForm):
class Meta:
@ -101,7 +105,7 @@ ADDITIONAL_REMOTE_CHOICES = [(_(u'официальный каталог'), _(u'
]
class RemoteForm(AbstractOrderForm):
additional = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(), choices=ADDITIONAL_REMOTE_CHOICES)
additional = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(), choices=ADDITIONAL_REMOTE_CHOICES, required=False)
class Meta:
model = Remote
@ -126,12 +130,10 @@ LANGS = [(_(u'Русский'), _(u'Русский'))]
from theme.models import Theme
class TranslationForm(AbstractOrderForm):
languages = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(),
choices=LANGS)
themes = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(),
choices=[(theme.id, theme.id) for theme in Theme.objects.language().filter()])
fr = forms.DateField(widget=forms.DateInput(attrs={'class': 'date dateFrom', 'placeholder': _(u'дд.мм.гггг')}))
to = forms.DateField(widget=forms.DateInput(attrs={'class': 'date dateTo', 'placeholder': _(u'дд.мм.гггг')}))
languages = forms.CharField(required=False)
themes = forms.CharField(required=False)
fr = forms.DateField(widget=forms.DateInput(attrs={'class': 'date dateFrom', 'placeholder': _(u'дд.мм.гггг')}), required=False)
to = forms.DateField(widget=forms.DateInput(attrs={'class': 'date dateTo', 'placeholder': _(u'дд.мм.гггг')}), required=False)
class Meta:
model = Translation
@ -195,4 +197,14 @@ class VisitForm(AbstractOrderForm):
if not avia_type:
return ''
else:
return ', '.join(avia_type)
return ', '.join(avia_type)
class AdvertiseForm(AbstractOrderForm):
action = '/service/com_rek/'
class Meta:
model = Advertising
class CallBackForm(forms.ModelForm):
class Meta:
model = CallBack
fields=('phone', 'person_inf')

@ -1,8 +1,18 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from views import ServiceView
from views import ServiceView, CallBackListView, VisitListView, TranslationListView, AdvertisingListView, \
ParticipationListView, RemoteListView,TicketsListView, Thanks
urlpatterns = patterns('',
url(r'service/thanks/$', Thanks.as_view()),
url(r'service/order/callback/$', CallBackListView.as_view()),
url(r'service/order/visit/$', VisitListView.as_view()),
url(r'service/order/translation/$', TranslationListView.as_view()),
url(r'service/order/advertising/$', AdvertisingListView.as_view()),
url(r'service/order/participation/$', ParticipationListView.as_view()),
url(r'service/order/remote/$', RemoteListView.as_view()),
url(r'service/order/tickets/$', TicketsListView.as_view()),
url(r'service/com_rek/$', 'service.views.advertise'),
url(r'service/(?P<url>.*)/$', ServiceView.as_view()),
)

@ -7,13 +7,14 @@ from haystack.query import EmptySearchQuerySet
from django.shortcuts import get_object_or_404
from django.http import Http404
import json
from functions.search_forms import CompanySearchForm
#from functions.search_forms import CompanySearchForm
from order_forms import TranslationForm, CatalogForm, VisitForm, RemoteForm, ParticipationForm, TicketsForm
from order_forms import TranslationForm, CatalogForm, VisitForm, RemoteForm, ParticipationForm, TicketsForm,\
AdvertiseForm, BuildStandForm
order_forms = {'translator': TranslationForm, 'catalog': CatalogForm, 'participation': ParticipationForm,
'remote': RemoteForm, 'tickets': TicketsForm, 'visit': VisitForm}
'remote': RemoteForm, 'tickets': TicketsForm, 'visit': VisitForm, 'buildstand': BuildStandForm}
class ServiceView(FormView):
@ -34,3 +35,51 @@ class ServiceView(FormView):
return service.template
def advertise(request):
if request.POST:
response = {'success': False}
form = AdvertiseForm(request.POST)
if form.is_valid():
form.save()
response['success'] = True
else:
response['errors'] = form.errors
return HttpResponse(json.dumps(response), content_type='application/json')
else:
raise HttpResponse('not ajax')
from service.models import CallBack, Visit, Translation, Advertising, Participation, Remote, Tickets
class AbstractOrderListView(ListView):
template_name = 'admin/service/order_list.html'
paginate_by = 20
class CallBackListView(AbstractOrderListView):
model = CallBack
class VisitListView(AbstractOrderListView):
model = Visit
class TranslationListView(AbstractOrderListView):
model = Translation
class AdvertisingListView(AbstractOrderListView):
model = Advertising
class ParticipationListView(AbstractOrderListView):
model = Participation
class RemoteListView(AbstractOrderListView):
model = Remote
class TicketsListView(AbstractOrderListView):
model = Tickets
class Thanks(TemplateView):
template_name = 'client/service/thank_u_page.html'

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

Loading…
Cancel
Save