remotes/origin/1203
Kotiuk Nazarii 11 years ago
commit 3a8ee32218
  1. 42
      accounts/admin.py
  2. 5
      accounts/admin_urls.py
  3. 186
      accounts/forms.py
  4. 13
      accounts/models.py
  5. 2
      accounts/urls.py
  6. 10
      core/admin_urls.py
  7. 38
      core/forms.py
  8. 51
      core/models.py
  9. 76
      core/utils.py
  10. 83
      core/views.py
  11. 4
      country/manager.py
  12. 0
      expobanner/__init__.py
  13. 156
      expobanner/admin.py
  14. 29
      expobanner/admin_urls.py
  15. 181
      expobanner/forms.py
  16. 1
      expobanner/management/__init__.py
  17. 1
      expobanner/management/commands/__init__.py
  18. 42
      expobanner/management/commands/banner_log_check_previous_day.py
  19. 67
      expobanner/management/commands/banner_log_update.py
  20. 77
      expobanner/managers.py
  21. 3
      expobanner/mixins.py
  22. 294
      expobanner/models.py
  23. 57
      expobanner/stat_views.py
  24. 159
      expobanner/static/banners/css/slider.css
  25. 10
      expobanner/static/banners/js/log.js
  26. 71
      expobanner/static/banners/js/slider.js
  27. 55
      expobanner/templates/banner.html
  28. 32
      expobanner/templates/grid.html
  29. 30
      expobanner/templates/group.html
  30. 74
      expobanner/templates/slider.html
  31. 0
      expobanner/templatetags/__init__.py
  32. 74
      expobanner/templatetags/banner.py
  33. 16
      expobanner/tests.py
  34. 13
      expobanner/urls.py
  35. 73
      expobanner/utils.py
  36. 100
      expobanner/views.py
  37. 3
      exposition/models.py
  38. 4
      exposition/search_indexes.py
  39. 18
      exposition/views.py
  40. 3
      functions/model_mixin.py
  41. 4
      functions/models_methods.py
  42. 100
      functions/pipeline.py
  43. 1
      functions/search_forms.py
  44. 3
      import_xls/utils.py
  45. 5
      meta/admin_urls.py
  46. 14
      meta/forms.py
  47. 65
      meta/models.py
  48. 47
      meta/views.py
  49. 2
      proj/admin_urls.py
  50. 16
      proj/decorators.py
  51. 80
      proj/settings.py
  52. 1
      proj/urls.py
  53. 45
      proj/views.py
  54. 42
      registration/backends/default/views.py
  55. 2
      settings/management/commands/do_inflect.py
  56. 4
      settings/redirect_views.py
  57. 74
      templates/admin/accounts/user_change.html
  58. 8
      templates/admin/accounts/user_list.html
  59. 36
      templates/admin/expobanner/banner_list.html
  60. 43
      templates/admin/expobanner/banner_stat.html
  61. 33
      templates/admin/expobanner/banners_control.html
  62. 73
      templates/admin/expobanner/default_form.html
  63. 34
      templates/admin/expobanner/default_list.html
  64. 71
      templates/admin/expobanner/paid_create.html
  65. 38
      templates/admin/expobanner/paid_list.html
  66. 43
      templates/admin/expobanner/paid_stat.html
  67. 32
      templates/admin/expobanner/paid_update.html
  68. 84
      templates/admin/expobanner/top_create.html
  69. 36
      templates/admin/expobanner/top_list.html
  70. 21
      templates/admin/import templates/import.html
  71. 9
      templates/admin/includes/admin_nav.html
  72. 63
      templates/admin/meta/create_seo_text.html
  73. 54
      templates/admin/meta/seo_admin_list.html
  74. 11
      templates/admin/meta/seo_confirm_delete.html
  75. 90
      templates/admin/page/new_page.html
  76. 58
      templates/admin/page/page_admin_list.html
  77. 11
      templates/admin/page/page_confirm_delete.html
  78. 5
      templates/admin/translator/translator_list.html
  79. 7
      templates/client/accounts/email_required.html
  80. 17
      templates/client/base_catalog.html
  81. 113
      templates/client/base_page.html
  82. 52
      templates/client/blank.html
  83. 67
      templates/client/expobanners/banner_stat.html
  84. 67
      templates/client/expobanners/paid_stat.html
  85. 6
      templates/client/exposition/exposition_detail.html
  86. 219
      templates/client/exposition/exposition_price.html
  87. 4
      templates/client/includes/banners/aside_1.html
  88. 4
      templates/client/includes/banners/aside_2.html
  89. 4
      templates/client/includes/banners/aside_3.html
  90. 4
      templates/client/includes/banners/aside_4.html
  91. 3
      templates/client/includes/banners/catalog_inner.html
  92. 3
      templates/client/includes/banners/detail_inner.html
  93. 3
      templates/client/includes/banners/header.html
  94. 3
      templates/client/includes/banners/search_under.html
  95. 13
      templates/client/includes/banners/tops.html
  96. 10
      templates/client/includes/exposition/expo_paid.html
  97. 102
      templates/client/includes/exposition/expo_top.html
  98. 32
      templates/client/includes/exposition/exposition_list.html
  99. 24
      templates/client/includes/exposition/exposition_object.html
  100. 19
      templates/client/includes/exposition/price.html
  101. Some files were not shown because too many files have changed in this diff Show More

@ -14,6 +14,7 @@ from models import User
from forms import UserForm, UserCreationForm, ChangePasswordForm, EmailAnnouncementForm, UserFilterForm
#custom views
from functions.admin_views import AdminView, AdminListView
from django.views.generic import UpdateView
class UserListView(AdminListView):
template_name = 'admin/accounts/user_list.html'
@ -21,24 +22,35 @@ class UserListView(AdminListView):
model = User
class EditUser(UpdateView):
model = User
form_class = UserForm
success_url = '/admin/accounts/all'
template_name = 'user_change.html'
def user_change(request, url):
"""
Return form of user and post it on the server.
If form is posted redirect on the page of all users.
"""
user = User.objects.safe_get(id=url)
# try get user by url if doesnt work by id
if user is None:
user = User.objects.safe_get(url=url)
#redirect to list of all users if cannot find user
if user is None:
try:
user = User.objects.get(url=url)
except User.DoesNotExist:
try:
user = User.objects.get(id=url)
except User.DoesNotExist, User.MultipleObjectsReturned:
return HttpResponseRedirect('/admin/accounts/all')
except User.MultipleObjectsReturned:
return HttpResponseRedirect('/admin/accounts/all')
if request.POST:
# bug with saving staff users(set is_staff to False)
staff = user.is_staff
form = UserForm(request.POST, instance=user)
form = UserForm(request.POST, request.FILES, instance=user)
if form.is_valid():
user = form.save()
@ -48,27 +60,29 @@ def user_change(request, url):
user.save()
return HttpResponseRedirect('/admin/accounts/all')
else:
form.fields['city'].widget.attrs['data-init-text'] = user.profile.city.name
if user.profile.city:
form.fields['city'].widget.attrs['data-init-text'] = user.profile.city.name
else:
profile = user.profile
data = {'country':profile.country_id, 'city': profile.city_id,
'title': profile.title, 'descriptions': profile.descriptions,
'keywords': profile.keywords, 'phone': profile.phone, 'web_page': profile.web_page,
'about': profile.about}
'about': profile.about, 'skype':profile.skype,'facebook':profile.facebook, 'linkedin':profile.linkedin,
'twitter':profile.twitter, 'vk':profile.vk}
form = UserForm(instance=user,initial=data)
if user.profile.city:
form.fields['city'].widget.attrs['data-init-text'] = user.profile.city.name
args = {}
args.update(csrf(request))
context = {}
context.update(csrf(request))
args['form'] = form
args['object'] = user
context['form'] = form
context['object'] = user
return render_to_response('user_change.html', args)
return render_to_response('user_change.html', context)
def create_admin(request):
if request.POST:

@ -1,12 +1,13 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from admin import UserListView
from admin import UserListView, EditUser
urlpatterns = patterns('',
#url(r'^registration/$', 'accounts.admin.registration'),
#url(r'^create_admin/$', 'accounts.admin.create_admin'),
#url(r'^create_md5user/$', 'accounts.admin.create_md5'),
url(r'^change/(.*)/$', 'accounts.admin.user_change'),
# url(r'^change/(?P<pk>.*)/$', EditUser.as_view()),
url(r'^change/(?P<url>.*)/$', 'accounts.admin.user_change'),
url(r'^all/$', UserListView.as_view()),
url(r'^reset_password_email/$', 'accounts.admin.reset_password_email'),
)

@ -5,6 +5,7 @@ from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.forms.util import ErrorList
from django.utils.translation import ugettext as _
from django.conf import settings
from models import User, Profile
from theme.models import Theme, Tag
from country.models import Area
@ -13,7 +14,7 @@ from country.models import Country
from city.models import City
from company.models import Company
from organiser.models import Organiser
#functions
# functions
from functions.form_check import translit_with_separator, is_latin
@ -27,7 +28,6 @@ def clean_relation_field(inst, field_name, model):
return None
class UserCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Пароль', widget=forms.PasswordInput(render_value=False))
password2 = forms.CharField(label='Повторите пароль', widget=forms.PasswordInput(render_value=False))
@ -36,7 +36,6 @@ class UserCreationForm(forms.ModelForm):
model = User
fields = ('email', 'first_name', 'last_name')
def clean_email(self):
"""
checking if user already exist
@ -56,7 +55,6 @@ class UserCreationForm(forms.ModelForm):
raise forms.ValidationError('Пароли не совпадают')
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data['password2'])
@ -66,6 +64,7 @@ class UserCreationForm(forms.ModelForm):
return user
class UserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
@ -76,24 +75,39 @@ class UserChangeForm(forms.ModelForm):
return self.initial['password']
class UserForm(forms.ModelForm):
#email = forms.EmailField(widget=forms.TextInput(attrs={'disabled' : True}), required=False)
country = forms.ChoiceField(label='Страна', choices=[(item.id, item.name) for item in Country.objects.all()], required=False)
city = forms.CharField(label='Город', widget=forms.HiddenInput())
company = forms.ChoiceField(label='Компания', choices=[(item.id, item.name) for item in Company.objects.language().all()], required=False)
organiser = forms.ChoiceField(label='Организатор', choices=[(item.id, item.name) for item in Organiser.objects.language().all()], required=False)
title = forms.CharField(widget=forms.TextInput(attrs={'style':'width: 550px'}), required=False)
descriptions = forms.CharField(widget=forms.TextInput(attrs={'style':'width: 550px'}), required=False)
keywords = forms.CharField(widget=forms.TextInput(attrs={'style':'width: 550px'}), required=False)
phone = forms.CharField(widget=forms.TextInput(attrs={'style':'width: 550px'}), required=False)
# email = forms.EmailField(widget=forms.TextInput(attrs={'disabled' : True}), required=False)
country = forms.ChoiceField(label='Страна', choices=[(item.id, item.name) for item in Country.objects.all()],
required=False)
city = forms.CharField(label='Город', widget=forms.HiddenInput(), required=False)
company = forms.ChoiceField(label='Компания',
choices=[(item.id, item.name) for item in Company.objects.language().all()],
required=False)
organiser = forms.ChoiceField(label='Организатор',
choices=[(item.id, item.name) for item in Organiser.objects.language().all()],
required=False, initial=None)
title = forms.CharField(widget=forms.TextInput(attrs={'style': 'width: 550px'}), required=False)
descriptions = forms.CharField(widget=forms.TextInput(attrs={'style': 'width: 550px'}), required=False)
keywords = forms.CharField(widget=forms.TextInput(attrs={'style': 'width: 550px'}), required=False)
phone = forms.CharField(widget=forms.TextInput(attrs={'style': 'width: 550px'}), required=False)
web_page = forms.URLField(required=False)
about = forms.CharField(widget=forms.Textarea())
about = forms.CharField(widget=forms.Textarea(), required=False)
avatar = forms.ImageField(required=False)
# ---
skype = forms.CharField(required=False)
facebook = forms.URLField(required=False)
twitter = forms.URLField(required=False)
linkedin = forms.URLField(required=False)
vk = forms.URLField(required=False)
new_password = forms.CharField(required=False, min_length=6, max_length=60,
widget=forms.TextInput(attrs={'class': 'new_password'}))
class Meta:
model = User
exclude = ('username', 'email','last_login', 'password', 'is_active', 'is_admin', 'is_superuser', 'is_staff'
'date_joined', 'date_registered', 'date_modified')
exclude = ('username', 'email', 'last_login', 'password', 'is_admin', 'rating', 'is_superuser', 'is_staff'
'date_joined',
'date_registered', 'date_modified')
def save(self, force_insert=False, force_update=False, commit=True):
@ -108,28 +122,34 @@ class UserForm(forms.ModelForm):
profile.phone = data.get('phone')
profile.web_page = data.get('web_page')
profile.about = data.get('about')
profile.skype = data.get('skype', '')
profile.facebook = data.get('facebook', '')
profile.twitter = data.get('twitter', '')
profile.linkedin = data.get('linkedin', '')
profile.vk = data.get('vk', '')
profile.avatar = data.get('avatar')
if data['new_password']:
new_pass = data['new_password']
user.set_password(new_pass)
user.email_user('Reset password', 'Your new password: "%s" ' % new_pass, settings.DEFAULT_FROM_EMAIL, )
if commit:
user.save()
profile.save()
return user
"""
def clean_url(self):
url = self.cleaned_data.get('url')
try:
user = User.objects.get(url=translit_with_separator(url))
if (user.url == translit_with_separator(url)):
if url:
if User.objects.get(url=translit_with_separator(url)):
raise forms.ValidationError('Такой урл уже занят')
else:
return url
except:
return url
raise forms.ValidationError('Такой урл уже занят')
"""
def clean_organiser(self):
return clean_relation_field(self, 'organiser', Organiser)
def clean_company(self):
return clean_relation_field(self, 'company', Company)
@ -139,23 +159,23 @@ class UserForm(forms.ModelForm):
def clean_city(self):
return clean_relation_field(self, 'city', City)
def clean_phone(self):
"""
phone code checking
"""
cleaned_data = super(UserForm, self).clean()
phone = cleaned_data.get('phone')
if not phone:
if not phone:
return
deduct = ('-','(',')','.',' ')
deduct = ('-', '(', ')', '.', ' ')
for elem in deduct:
phone = phone.replace(elem, '')
if phone.isdigit():
return phone
else:
raise forms.ValidationError('Введите правильный код страны')
"""
def clean_web_page(self):
cleaned_data = super(UserForm, self).clean()
@ -171,6 +191,7 @@ class UserForm(forms.ModelForm):
return forms.ValidationError('Введите правильный адрес страници')
"""
class ChangePasswordForm(forms.Form):
"""
Form to change password
@ -183,7 +204,8 @@ class ChangePasswordForm(forms.Form):
attrs={'placeholder': _(u'Придумайте новый пароль')}))
new_password_confirm = forms.CharField(label=_(u'Confirm password'), required=True,
widget=forms.PasswordInput(render_value=False,
attrs={'placeholder': _(u'Повторите новый пароль')}))
attrs={
'placeholder': _(u'Повторите новый пароль')}))
def clean(self):
data = super(ChangePasswordForm, self).clean()
@ -191,7 +213,7 @@ class ChangePasswordForm(forms.Form):
password2 = data.get('new_password_confirm')
if not password1 or not password2:
return data
# self._errors['new_password'] = ErrorList([_(u'Different passwords!')])
# self._errors['new_password'] = ErrorList([_(u'Different passwords!')])
# return data
if password1 and password2 and password1 != password2:
# check if passwords exists and equal
@ -200,7 +222,7 @@ class ChangePasswordForm(forms.Form):
del data['new_password_confirm']
del data['new_password']
return data
if not password1.isdigit() and any(char.isdigit() for char in password1) and len(password1)>5:
if not password1.isdigit() and any(char.isdigit() for char in password1) and len(password1) > 5:
# password must contain digits and letters and length > 5
return data
else:
@ -210,33 +232,35 @@ class ChangePasswordForm(forms.Form):
del data['new_password_confirm']
return data
class EmailAnnouncementForm(forms.Form):
data = [(1, _(u'Получать приглашения, сообщения и другую корреспонденцию от пользователей Expomap')),
(2, _(u'Получать обзор событий')),
(3, _(u'Получать новости'))]
(2, _(u'Получать обзор событий')),
(3, _(u'Получать новости'))]
announcement = forms.MultipleChoiceField(choices=data, widget=forms.CheckboxSelectMultiple())
class RegistrationCompleteForm(forms.ModelForm):
country = forms.ModelChoiceField(label='Страна', queryset= 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(обязательно)')}))
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],
choices=[(str(c.phone_code), '+' + str(c.phone_code)) for c in
Country.objects.all() if c.phone_code is not None],
widget=forms.Select(attrs={'class': 'select2'}))
code_city = forms.CharField(label=_(u'код города'))
phone = forms.CharField(label=_(u'ваш номер'))
class Meta:
model = User
fields = ('url',)
def save(self, force_insert=False, force_update=False, commit=True):
user = super(RegistrationCompleteForm, self).save(commit=False)
data = self.cleaned_data
phone = data['code_country']+data['code_city']+data['phone']
phone = data['code_country'] + data['code_city'] + data['phone']
user.profile.phone = int(phone)
user.profile.country = data['country']
@ -253,7 +277,6 @@ class RegistrationCompleteForm(forms.ModelForm):
except City.DoesNotExist:
return None
def clean_url(self):
url = self.cleaned_data['url']
if not is_latin(url):
@ -267,6 +290,36 @@ class RegistrationCompleteForm(forms.ModelForm):
class SocialRegistrationCompleteForm(RegistrationCompleteForm):
email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': _(u'Email')}), required=True)
class Meta:
model = User
fields = ['email', 'url']
def save(self, force_insert=False, force_update=False, commit=True):
email = self.cleaned_data['email']
if User.objects.filter(email=email).exists():
# pass to the view user, that had account before
user = User.objects.get(email=email)
# social = UserSocialAuth.objects.get(user=self.instance)
# social.user = user # that cause AuthAlreadyAssociated error!
else:
# create new user, with data from social auth
user = super(RegistrationCompleteForm, self).save(commit=False) # creating new user
user.username = email
data = self.cleaned_data
phone = data['code_country'] + data['code_city'] + data['phone']
user.profile.phone = int(phone)
user.profile.country = data['country']
user.profile.city = data['city']
user.profile.save()
# if commit:
user.save()
return user
class RecoveryForm(forms.Form):
email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': _(u'Email')}))
@ -283,10 +336,13 @@ class RecoveryForm(forms.Form):
raise forms.ValidationError(_(u'Пользователь с таким емейлом не зарегестрирован'))
from django.db.models import Q
class UserFilterForm(forms.Form):
model = User
email = forms.CharField(label=_(u'Email'), required=False)
search_req = forms.CharField(label=_(u'Введите e-mail, имя или фамилию для запроса'), required=False)
def filter(self):
"""
@ -295,27 +351,31 @@ class UserFilterForm(forms.Form):
"""
data = self.cleaned_data
email = data['email']
search_req = data['search_req']
words = search_req.split()
model = self.model
qs = model.objects.all()
if email:
qs = qs.filter(email__contains=email)
if len(words) > 1:
qs = qs.filter(Q(first_name__contains=words[0]) & Q(last_name__contains=words[1]))
elif words:
qs = qs.filter(
Q(email__contains=search_req) | Q(first_name__contains=search_req) | Q(last_name__contains=search_req))
return qs
class FeedFilterForm(forms.Form):
data_with_parents = None
filter = None
th = forms.MultipleChoiceField(label=_(u'Тематика'), choices=[(item.id, item.name) for item in Theme.active.all()],
required=False, widget=forms.CheckboxSelectMultiple())
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.language().all()],
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.expo_countries()]
)
)
ci = forms.MultipleChoiceField(label=_(u'Город'), required=False, widget=forms.CheckboxSelectMultiple(),
choices=[(item.id, item.name) for item in City.used.expo_cities()]
@ -336,21 +396,19 @@ class FeedFilterForm(forms.Form):
self.filter = filter
self.data_with_parents = self.get_form_data(filter)
def get_form_data(self, filter):
if filter.area.exists():
areas = [{'name':'area', 'id':item.id, 'parent':None, 'text':item.name} for item in filter.area.all()]
areas = [{'name': 'area', 'id': item.id, 'parent': None, 'text': item.name} for item in filter.area.all()]
else:
areas = []
if filter.country.exists():
cos = []
for country in filter.country.all():
cos.append({'name':'area', 'id':country.area_id, 'text': country.area.name, 'children':{
'id': country.id, 'name':'co', 'text': country.name
}
cos.append({'name': 'area', 'id': country.area_id, 'text': country.area.name, 'children': {
'id': country.id, 'name': 'co', 'text': country.name
}
})
else:
cos = []
@ -358,29 +416,27 @@ class FeedFilterForm(forms.Form):
if filter.city.exists():
cis = []
for city in filter.city.all():
cis.append({'name':'area', 'id': city.country.area_id, 'text': city.country.area.name, 'children':{
'id': city.country_id, 'name':'co', 'text': city.country.name, 'children':{
'name':'ci', 'id':city.id, 'text':city.name
}
}
cis.append({'name': 'area', 'id': city.country.area_id, 'text': city.country.area.name, 'children': {
'id': city.country_id, 'name': 'co', 'text': city.country.name, 'children': {
'name': 'ci', 'id': city.id, 'text': city.name
}
}
})
else:
cis = []
if filter.theme.exists():
ths = [{'name':'th', 'id':item.id, 'parent':None, 'text':item.name} for item in filter.theme.all()]
ths = [{'name': 'th', 'id': item.id, 'parent': None, 'text': item.name} for item in filter.theme.all()]
else:
ths = []
if filter.tag.exists():
tgs = []
for tag in filter.tag.all():
tgs.append({'name':'th', 'id':tag.theme_id, 'text': tag.theme.name, 'children':{
'id': tag.id, 'name':'tg', 'text': tag.name
}
tgs.append({'name': 'th', 'id': tag.theme_id, 'text': tag.theme.name, 'children': {
'id': tag.id, 'name': 'tg', 'text': tag.name
}
})
else:
tgs = []
@ -418,4 +474,4 @@ class FeedFilterForm(forms.Form):
if tg:
res = ast.literal_eval(tg)
return res
return tg
return tg

@ -32,7 +32,8 @@ class UserManager(BaseUserManager):
raise ValueError('Вы должни ввести электронную почту')
user= self.model(
email = UserManager.normalize_email(email),first_name = first_name,last_name = last_name,
email = UserManager.normalize_email(email),
first_name = first_name,last_name = last_name,
username = UserManager.normalize_email(email),
is_staff=False, is_active=False, is_superuser=False,
last_login=now, date_joined=now, **extra_fields
@ -42,7 +43,7 @@ class UserManager(BaseUserManager):
user.save(using=self._db)
return user
def create_social_user(self,username, first_name, last_name, password=None, **extra_fields):
def create_social_user(self, username, first_name, last_name, password=None, **extra_fields):
now = timezone.now()
# generate random password
digits = random.sample(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), 4)
@ -116,7 +117,7 @@ class User(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(verbose_name='First name', max_length=255)
last_name = models.CharField(verbose_name='Last name', max_length=255)
rating = models.IntegerField(default=100)# добавить индекс в базе
url = models.SlugField(blank=True)
url = models.SlugField(blank=True)#, unique=True, null=True)
#
is_active = models.BooleanField(default=0) # СДЕЛАТЬ проверку на емейле
is_staff = models.BooleanField(default=0)
@ -382,8 +383,10 @@ def calculate_rating(user):
user_rating_fields = {'position': 5, 'company': 5, 'url': 10}
profile_rating_fields = {'country': 5, 'city': 5, 'phone': 10, 'facebook': 5, 'twitter': 5, 'linkedin': 5, 'vk': 5,
'web_page': 10, 'avatar': 20, 'about': 15}
# доделать "Отметки на выставках, за каждую", "Подписка на рассылку", "Добавление фото, за каждую", "Добавление компании, за каждую опубликованную"
'''
TODO: доделать "Отметки на выставках, за каждую", "Подписка на рассылку", "Добавление фото, за каждую",
"Добавление компании, за каждую опубликованную"
'''
# base rating
rating = 100
for key, value in user_rating_fields.iteritems():

@ -16,6 +16,7 @@ urlpatterns = patterns('',
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/export/$', 'core.views.download_workbook'),
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())),
@ -28,6 +29,7 @@ urlpatterns = patterns('',
url(r'^user/(?P<url>.*)/events/(?P<page>\d+)/$', UserView.as_view()),
url(r'^user/(?P<url>.*)/events/$', UserView.as_view()),
url(r'^user/(?P<url>.*)/$', UserView.as_view()),
url(r'^inactive-user/$', 'registration.backends.default.views.inactive_user_message'),
#url(r'^profile/messages/(?P<user>.*)/$', login_required(MessagesView.as_view())),
#url(r'^profile/messages/$', login_required(MessagesView.as_view())),

@ -0,0 +1,10 @@
from django.conf.urls import url, patterns
from views import NewPage, PageList, EditPage, DeletePage, PageDetailed
urlpatterns = patterns('',
url(r'^new/$', NewPage.as_view(), name='new_page' ),
url(r'^all/$', PageList.as_view(), name = 'page_list'),
url(r'^edit/(?P<url>.*)/$', EditPage.as_view(), name='edit_page'),
url(r'^delete/(?P<url>.*)/$', DeletePage.as_view(), name='delete_page'),
url(r'^(?P<url>.*)/$', PageDetailed.as_view(), name='page_view'),
)

@ -6,7 +6,8 @@ from place_exposition.models import PlaceExposition
from place_conference.models import PlaceConference
from django.utils.translation import ugettext_lazy as _
from haystack.query import SearchQuerySet, EmptySearchQuerySet
from hvad.forms import TranslatableModelForm
from models import Page
class PlaceSearchForm(forms.Form):
q = forms.CharField(label=_(u'Поиск'), required=False)
@ -45,3 +46,38 @@ class CallbackForm(forms.Form):
def send(self):
phone = self.cleaned_data['callback_phone']
send_mail(phone, phone, None, [settings.CALLBACK_EMAIL])
# ------------------ Page Form -----------------------
from django.conf import settings
from django.forms import Textarea
from ckeditor.widgets import CKEditorWidget
class PageForm(TranslatableModelForm):
# language = 'ru'
class Meta:
model = Page
fields = ['url','title','h1','descriptions','keywords', 'body' ]
widgets = {
'body':CKEditorWidget,
'keywords':Textarea,
'descriptions':Textarea,
}
def clean_url(self):
url = self.cleaned_data.get('url', None)
if url[0] == '/':
url = url[1:]
if url[-1] == '/':
url = url[:-1]
if ' ' in url:
url.replace(' ', '_')
return url

@ -1,12 +1,18 @@
# -*- coding: utf-8 -*-
from django.contrib.syndication.views import Feed
from django.shortcuts import get_object_or_404
from django.db import models
from exposition.models import Exposition
from settings.models import create_transl_fields
from theme.models import Theme
from country.models import Country
from city.models import City
from hvad.models import TranslatableModel, TranslatedFields
# ----------------------- RSS -------------------------- #
EXPO_ON_PAGE = 10
# nearest expositions at all
@ -85,4 +91,47 @@ class ThemeFeeds(Feed):
return obj.main_title
def items(self, obj):
return Exposition.enable.upcoming().filter(theme = obj)[:NUM_ITEMS_ON_PAGE]
return Exposition.enable.upcoming().filter(theme = obj)[:NUM_ITEMS_ON_PAGE]
# ------------------------ Page model --------------------------- #
from django.conf import settings
from django.core.urlresolvers import reverse
class Page(TranslatableModel):
url = models.SlugField(unique=True)
translations = TranslatedFields(
h1 = models.CharField(max_length=255),
body = models.TextField(),
# 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),
)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
def get_absolute_url(self):
return reverse('page_view', args=[self.url])
def save(self, *args, **kwargs):
super(Page,self).save(*args, **kwargs)
all_field_names = list(self._translated_field_names)
clear_f_n = []
for field_name in all_field_names:
if field_name not in ['master', 'master_id',u'id', 'language_code']:
clear_f_n.append(field_name)
field_items = {field_name:getattr(self, field_name) for field_name in clear_f_n}
langs = [lan[0] for lan in settings.LANGUAGES]
for lang in langs:
if lang not in self.get_available_languages():
self.translate(lang)
for field in clear_f_n:
setattr(self, field, field_items.get(field, ''))
obj = super(Page,self).save(*args, **kwargs)
return obj
def __unicode__(self):
return self.url

@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
import xlwt
import datetime
from exposition.models import Exposition
from conference.models import Conference
from django.core.exceptions import ObjectDoesNotExist
HEADER_STYLE = xlwt.easyxf('font: bold on')
DEFAULT_STYLE = xlwt.easyxf()
CELL_STYLE_MAP = (
(datetime.date, xlwt.easyxf(num_format_str='DD/MM/YYYY')),
(datetime.time, xlwt.easyxf(num_format_str='HH:MM')),
(bool, xlwt.easyxf(num_format_str='BOOLEAN')),
)
def multi_getattr(obj, attr, default=None):
attributes = attr.split(".")
for i in attributes:
try:
obj = getattr(obj, i)
except AttributeError:
if default:
return default
else:
return '-'
return obj
def get_column_cell(obj, name):
try:
attr = multi_getattr(obj, name)
except ObjectDoesNotExist:
return ''
if hasattr(attr, '_meta'):
# A Django Model (related object)
return unicode(attr).strip()
elif hasattr(attr, 'all'):
# A Django queryset (ManyRelatedManager)
return ', '.join(unicode(x).strip() for x in attr.all())
return attr
def queryset_to_workbook(queryset, columns, header_style=None, default_style=None, cell_style_map=None):
workbook = xlwt.Workbook()
report_date = datetime.date.today()
sheet_name = 'Export {0}'.format(report_date.strftime('%Y-%m-%d'))
sheet = workbook.add_sheet(sheet_name)
if not header_style:
header_style = HEADER_STYLE
if not default_style:
default_style = DEFAULT_STYLE
if not cell_style_map:
cell_style_map = CELL_STYLE_MAP
obj = queryset[0]
for y, column in enumerate(columns):
header_list=[u'Название события',u'Страна',u'Город',u'Место проведения', u'Дата начала', u'Дата окончания']
sheet.write(0, y, header_list[y], header_style)
for x, obj in enumerate(queryset, start=1):
for y, column in enumerate(columns):
value = get_column_cell(obj, column)
style = default_style
for value_type, cell_style in cell_style_map:
if isinstance(value, value_type):
style = cell_style
sheet.write(x, y, value, style)
return workbook

@ -4,7 +4,8 @@ from country.models import Country
from city.models import City
from place_exposition.models import PlaceExposition
from place_conference.models import PlaceConference
from django.views.generic import ListView, FormView
from django.views.generic import ListView, CreateView, DeleteView, UpdateView, DetailView
from django.core.urlresolvers import reverse_lazy
from functions.views_help import split_params
from django.utils.translation import ugettext as _
@ -199,3 +200,83 @@ class PlacePhotoView(PlaceListView):
context = super(PlacePhotoView, self).get_context_data(**kwargs)
context['object'] = self.obj
return context
# --------------------- Page views ------------------------
from forms import PageForm
from models import Page
class NewPage(CreateView):
form_class= PageForm
template_name = 'new_page.html'
success_url = '/admin/page/all/'
class PageList(ListView):
paginate_by = 10
template_name = 'page_admin_list.html'
model = Page
order = 'created'
from django import forms
from django.http import HttpResponseRedirect
class EditPage(UpdateView):
model = Page
template_name = 'new_page.html'
form_class = PageForm
slug_url_kwarg = 'url'
slug_field = 'url'
def get_context_data(self, **kwargs):
context = super(EditPage,self).get_context_data(**kwargs)
context['request'] = self.request
return context
def get_success_url(self):
return HttpResponseRedirect('/admin/page/all/')
class DeletePage(DeleteView):
template_name = 'admin/page/page_confirm_delete.html'
model = Page
success_url = reverse_lazy('page_list')
slug_field = 'url'
slug_url_kwarg = 'url'
class PageDetailed(DetailView):
model = Page
template_name = 'client/base_page.html'
slug_field = 'url'
slug_url_kwarg = 'url'
# ------------ XLS Export ----------------
from django.http import HttpResponse
from .utils import queryset_to_workbook
from exposition.models import Exposition
from conference.models import Conference
def download_workbook(request):
data = [(36539, 'expo'),(36602, 'expo'), (3033, 'conf'), (3053, 'conf')]
qs = []
for obj in data:
if obj[1] == 'expo':
qs.append(Exposition.objects.get(id=obj[0]))
if obj[1] == 'conf':
qs.append(Conference.objects.get(id=obj[0]))
columns = (
'name',
'country.name',
'city.name',
'place.name',
'data_begin',
'data_end')
workbook = queryset_to_workbook(qs, columns)
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="export.xls"'
workbook.save(response)
return response

@ -7,13 +7,13 @@ 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:

@ -0,0 +1,156 @@
# -*- coding: utf-8 -*-
from django.views.generic import TemplateView, CreateView, ListView, UpdateView, DetailView
from django.conf import settings
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from expobanner.models import URL, BannerGroup, Banner, Paid
from expobanner.forms import UrlCreateForm, BannerCreateGroupForm, BannerCreateForm, BannerGroupUpdateForm,\
PaidCreateForm, PaidUpdateForm, TopCreateForm
from exposition.models import Exposition
class BannersControl(TemplateView):
template_name = 'admin/expobanner/banners_control.html'
# CREATE VIEWS
class AbstractCreate(CreateView):
template_name = 'admin/expobanner/default_form.html'
success_url = '/admin/expobanners/banners/control/'
class CreateUrl(AbstractCreate):
model = URL
form_class = UrlCreateForm
class CreateBannerGroup(AbstractCreate):
model = BannerGroup
form_class = BannerCreateGroupForm
class CreateBanner(AbstractCreate):
model = Banner
form_class = BannerCreateForm
# LISTS VIEWS
class AbstractList(ListView):
paginate_by = settings.ADMIN_PAGINATION
template_name = 'admin/expobanner/default_list.html'
def get_context_data(self, **kwargs):
context = super(AbstractList, self).get_context_data(**kwargs)
context['verbose'] = self.verbose
return context
class UrlList(AbstractList):
model = URL
verbose = u'Список урлов'
class BannerGroupList(AbstractList):
model = BannerGroup
verbose = u'Список груп'
class BannerList(AbstractList):
model = Banner
verbose = u'Список банеров'
template_name = 'admin/expobanner/banner_list.html'
def get_queryset(self):
qs = super(BannerList, self).get_queryset()
qs = qs.filter(group__isnull=False)
return qs
# UPDATE VIEWS
class AbstractUpdate(UpdateView):
template_name = 'admin/expobanner/default_form.html'
success_url = '/admin/expobanners/banners/control/'
class UrlUpdate(AbstractUpdate):
model = URL
form_class = UrlCreateForm
class BannerGroupUpdate(AbstractUpdate):
model = BannerGroup
form_class = BannerGroupUpdateForm
class BannerUpdate(AbstractUpdate):
model = Banner
form_class = BannerCreateForm
class BannerStat(DetailView):
model = Banner
template_name = 'admin/expobanner/banner_stat.html'
class PaidList(ListView):
model = Exposition
template_name = 'admin/expobanner/paid_list.html'
paginate_by = settings.ADMIN_PAGINATION
def get_queryset(self):
return self.model.objects.language().filter(paid_new__isnull=False)
class PaidCreate(CreateView):
form_class = PaidCreateForm
template_name = 'admin/expobanner/paid_create.html'
success_url = '/admin/expobanners/paid/list/'
class PaidUpdate(UpdateView):
model = Paid
form_class = PaidUpdateForm
template_name = 'admin/expobanner/paid_update.html'
success_url = '/admin/expobanners/paid/list/'
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
"""
initial = super(PaidUpdate, self).get_initial()
obj = self.object
initial['tickets'] = obj.tickets.url
initial['participation'] = obj.participation.url
initial['official'] = obj.official.url
return initial
def get_context_data(self, **kwargs):
context = super(PaidUpdate, self).get_context_data(**kwargs)
obj = self.object
context['exposition'] = obj.get_event()
return context
def paid_turn(request, pk, status):
paid = get_object_or_404(Paid, pk=pk)
if status == 'on':
paid.public = True
else:
paid.public = False
paid.save()
return HttpResponseRedirect('/admin/expobanners/paid/list/')
class PaidStat(DetailView):
model = Paid
template_name = 'admin/expobanner/paid_stat.html'
class TopList(ListView):
model = Exposition
template_name = 'admin/expobanner/top_list.html'
paginate_by = settings.ADMIN_PAGINATION
def get_queryset(self):
return self.model.objects.language().filter(top__isnull=False)
class TopCreate(CreateView):
form_class = TopCreateForm
template_name = 'admin/expobanner/top_create.html'
success_url = '/admin/expobanners/top/list/'

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from expobanner.admin import *
urlpatterns = patterns('expobanner.admin',
# banners
url(r'^banners/control/$', BannersControl.as_view(), name='expobanner-baneers_control'),
url(r'^banners/url/$', CreateUrl.as_view(), name='expobanner-create_url'),
url(r'^banners/group/$', CreateBannerGroup.as_view(), name='expobanner-create_group'),
url(r'^banners/banner/$', CreateBanner.as_view(), name='expobanner-create_banner'),
url(r'^banners/url/list/$', UrlList.as_view(), name='expobanner-list_url'),
url(r'^banners/group/list/$', BannerGroupList.as_view(), name='expobanner-list_group'),
url(r'^banners/banner/list/$', BannerList.as_view(), name='expobanner-list_banner'),
url(r'^banners/url/(?P<pk>\d+)/edit/$', UrlUpdate.as_view(), name='expobanner-update_url'),
url(r'^banners/group/(?P<pk>\d+)/edit/$', BannerGroupUpdate.as_view(), name='expobanner-update_group'),
url(r'^banners/banner/(?P<pk>\d+)/edit/$', BannerUpdate.as_view(), name='expobanner-update_banner'),
url(r'^banners/banner/(?P<pk>\d+)/stat/$', BannerStat.as_view(), name='expobanner_stat_banner'),
# paid
url(r'^paid/list/$', PaidList.as_view(), name='expobanner-list_paid'),
url(r'^paid/(?P<pk>\d+)/edit/$', PaidUpdate.as_view(), name='expobanner-update_paid'),
url(r'^paid/$', PaidCreate.as_view(), name='expobanner-create_paid'),
url(r'^paid/turn/(?P<pk>\d+)/(?P<status>.*)/$', paid_turn, name='expobanner-paid-turn'),
url(r'^paid/(?P<pk>\d+)/stat/$', PaidStat.as_view(), name='expobanner_stat_paid'),
# top
url(r'^top/list/$', TopList.as_view(), name='expobanner-list_top'),
url(r'^top/(?P<pk>\d+)/edit/$', PaidUpdate.as_view(), name='expobanner-update_top'),
url(r'^top/$', TopCreate.as_view(), name='expobanner-create_top'),
url(r'^top/(?P<pk>\d+)/stat/$', PaidStat.as_view(), name='expobanner_stat_top'),
)

@ -0,0 +1,181 @@
# -*- coding: utf-8 -*-
from django import forms
from expobanner.models import URL, BannerGroup, Banner, Paid, Top
from exposition.models import Exposition
from country.models import Country
from city.models import City
from theme.models import Theme, Tag
class UrlCreateForm(forms.ModelForm):
verbose = u'Создать урл'
class Meta:
model = URL
exclude = ['created_at', 'updated_at', 'sites']
class BannerCreateGroupForm(forms.ModelForm):
verbose = u'Создать групу'
class Meta:
model = BannerGroup
exclude = ['created_at', 'updated_at', 'speed']
class BannerGroupUpdateForm(BannerCreateGroupForm):
verbose = u'Изменить групу'
class Meta:
model = BannerGroup
exclude = ['created_at', 'updated_at', 'slug', 'speed']
class BannerCreateForm(forms.ModelForm):
verbose = u'Создать банер'
#country = forms.ChoiceField(label=u'Страна', choices=[('', ' ')] + [(c.id, c.name) for c in Country.objects.all()], required=False)
#theme = forms.ChoiceField(label=u'Тематика', required=False,
# choices=[('', ' ')] + [(item.id, item.name) for item in Theme.objects.language().all()])
#city = forms.CharField(label=u'Город', widget=forms.HiddenInput(), required=False)
#tag = forms.CharField(label=u'Тег', widget=forms.HiddenInput(), required=False)
class Meta:
model = Banner
exclude = ['created_at', 'updated_at', 'often', 'paid', 'stat_pswd']
class ClientStatForm(forms.Form):
stat_pswd = forms.CharField(label=u'Введите пароль:')
def check_pass(self, obj):
pswd = self.cleaned_data['stat_pswd']
return obj.stat_pswd == pswd
class PaidCreateForm(forms.ModelForm):
verbose = u'Создать проплаченую выставку'
exposition = forms.CharField(label=u'Выставка', widget=forms.HiddenInput())
tickets = forms.URLField(label=u'Линк на билеты')
participation = forms.URLField(label=u'Линк на участие')
official = forms.URLField(label=u'Линк на официальный сайт')
class Meta:
model = Paid
fields = ['logo', 'organiser', 'public']
def save(self, commit=True):
paid = super(PaidCreateForm, self).save(commit=False)
if commit:
expo = self.cleaned_data['exposition']
tickets = self.cleaned_data['tickets']
tickets_link = Banner.objects.create_for_paid(expo, tickets, 'tickets')
participation = self.cleaned_data['participation']
participation_link = Banner.objects.create_for_paid(expo, participation, 'participation')
official = self.cleaned_data['official']
official_link = Banner.objects.create_for_paid(expo, official, 'official')
catalog = expo.get_permanent_url()
catalog_link = Banner.objects.create_for_paid(expo, catalog, 'catalog')
paid.tickets = tickets_link
paid.participation = participation_link
paid.official = official_link
paid.catalog = catalog_link
paid.save()
expo.paid_new = paid
expo.save()
return paid
def clean_exposition(self):
expo_id = self.cleaned_data['exposition']
try:
expo = Exposition.objects.get(id=expo_id)
except Exposition.DoesNotExist:
raise forms.ValidationError(u'Такой выставки не существует')
return expo
class PaidUpdateForm(forms.ModelForm):
tickets = forms.URLField(label=u'Линк на билеты')
participation = forms.URLField(label=u'Линк на участие')
official = forms.URLField(label=u'Линк на официальный сайт')
class Meta:
model = Paid
fields = ['logo', 'organiser', 'public']
def save(self, commit=True):
paid = super(PaidUpdateForm, self).save(commit=False)
if commit:
tickets = self.cleaned_data['tickets']
b_tickets = paid.tickets
if tickets != b_tickets.url:
b_tickets.url = tickets
b_tickets.save()
participation = self.cleaned_data['participation']
b_participation = paid.participation
if participation != b_participation.url:
b_participation.url = participation
b_participation.save()
official = self.cleaned_data['official']
b_official = paid.official
if official != b_official.url:
b_official.url = official
b_official.save()
paid.save()
return paid
class TopCreateForm(forms.ModelForm):
verbose = u'Создать выставку в топе'
exposition = forms.CharField(label=u'Выставка', widget=forms.HiddenInput())
country = forms.MultipleChoiceField(label=u'Страна', choices=[('', ' ')] + [(c.id, c.name) for c in Country.objects.all()], required=False)
theme = forms.MultipleChoiceField(label=u'Тематика', required=False,
choices=[('', ' ')] + [(item.id, item.name) for item in Theme.objects.language().all()])
excluded_cities = forms.CharField(label=u'Город', widget=forms.HiddenInput(), required=False)
excluded_tags = forms.CharField(label=u'Тег', widget=forms.HiddenInput(), required=False)
class Meta:
model = Top
fields = ['catalog', 'position', 'theme', 'excluded_tags', 'country', 'excluded_cities', 'fr', 'to']
def save(self, commit=True):
top = super(TopCreateForm, self).save(commit=False)
# Prepare a 'save_m2m' method for the form,
old_save_m2m = self.save_m2m
def save_m2m():
old_save_m2m()
# This is where we actually link the pizza with toppings
top.theme.clear()
for theme in self.cleaned_data['theme']:
top.theme.add(theme)
self.save_m2m = save_m2m
if commit:
expo = self.cleaned_data['exposition']
top.save()
self.save_m2m()
expo.top = top
expo.save()
return top
def clean_theme(self):
theme_ids = self.cleaned_data['theme']
if theme_ids:
return Theme.objects.filter(id__in=theme_ids)
return None
def clean_country(self):
country_ids = self.cleaned_data['country']
if country_ids:
return Country.objects.filter(id__in=country_ids)
return None
def clean_exposition(self):
expo_id = self.cleaned_data['exposition']
try:
expo = Exposition.objects.get(id=expo_id)
except Exposition.DoesNotExist:
raise forms.ValidationError(u'Такой выставки не существует')
return expo

@ -0,0 +1 @@
__author__ = 'kotzilla'

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
from datetime import date, timedelta
from django.core.management.base import BaseCommand
from expobanner.models import Log, LogStat, Banner
from django.conf import settings
class Command(BaseCommand):
def handle(self, *args, **options):
prev_day = date.today() - timedelta(days=1)
for banner in Banner.objects.select_related('group').filter():
try:
logstat = LogStat.objects.get(banner=banner, group=banner.group, date=prev_day)
except LogStat.DoesNotExist:
logstat = LogStat(banner=banner, group=banner.group, date=prev_day)
views = Log.objects.filter(datetime__startswith=prev_day,
banner=banner,
group=banner.group,
type=1).count()
clicks = Log.objects.filter(datetime__startswith=prev_day,
banner=banner,
group=banner.group,
type=2).count()
unique_views = Log.objects.filter(datetime__startswith=prev_day,
banner=banner,
group=banner.group,
type=1).values('ip').distinct().count()
unique_clicks = Log.objects.filter(datetime__startswith=prev_day,
banner=banner,
group=banner.group,
type=2).values('ip').distinct().count()
if not logstat.click or logstat.click < clicks:
logstat.click = clicks
if not logstat.view or logstat.view < views:
logstat.view = views
if not logstat.unique_click or logstat.unique_click < unique_clicks:
logstat.unique_click = unique_clicks
if not logstat.unique_view or logstat.unique_view < unique_views:
logstat.unique_view = unique_views
logstat.save()

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
from datetime import date
from django.core.management.base import BaseCommand
from expobanner.models import Log, LogStat, Banner, PaidStat
from exposition.models import Exposition
class Command(BaseCommand):
def handle(self, *args, **options):
today = date.today()
# banners
for banner in Banner.objects.select_related('group').filter(public=True, group__isnull=False):
try:
logstat = LogStat.objects.get(banner=banner, group=banner.group, date=today)
except LogStat.DoesNotExist:
logstat = LogStat(banner=banner, group=banner.group, date=today)
views = Log.objects.filter(datetime__startswith=today,
banner=banner,
group=banner.group,
type=1).count()
clicks = Log.objects.filter(datetime__startswith=today,
banner=banner,
group=banner.group,
type=2).count()
unique_views = Log.objects.filter(datetime__startswith=today,
banner=banner,
group=banner.group,
type=1).values('ip').distinct().count()
unique_clicks = Log.objects.filter(datetime__startswith=today,
banner=banner,
group=banner.group,
type=2).values('ip').distinct().count()
logstat.click = clicks
logstat.view = views
logstat.unique_click = unique_clicks
logstat.unique_view = unique_views
logstat.save()
# paid expos
expos = list(Exposition.objects.select_related('paid_new').filter(paid_new__isnull=False))
for expo in expos:
paid = expo.paid_new
try:
paidstat = PaidStat.objects.get(paid=paid, date=today)
except PaidStat.DoesNotExist:
paidstat = PaidStat(paid=paid, date=today)
t_clicks = Log.objects.filter(datetime__startswith=today, banner=paid.tickets, type=2).count()
p_clicks = Log.objects.filter(datetime__startswith=today, banner=paid.participation, type=2).count()
o_clicks = Log.objects.filter(datetime__startswith=today, banner=paid.official, type=2).count()
c_clicks = Log.objects.filter(datetime__startswith=today, banner=paid.catalog, type=2).count()
paidstat.tickets_clicks = t_clicks
paidstat.participation_clicks = p_clicks
paidstat.official_clicks = o_clicks
paidstat.catalog_clicks = c_clicks
paidstat.save()

@ -0,0 +1,77 @@
# -*- coding: utf-8 -*
from datetime import date
from random import choice, shuffle
from django.db import models
from django.db.models import Q
from django.core.cache import cache
class BiasedManager(models.Manager):
def by_time(self, **kwargs):
all = super(BiasedManager, self).get_query_set().filter(**kwargs)
result = []
for i in all:
for j in range(i.often):
result.append(i)
return result
def one(self, **kwargs):
return choice(self.by_time(**kwargs))
def by_often(self, **kwargs):
result = self.by_time(**kwargs)
shuffle(result)
return result
def create_for_paid(self, expo, url, role):
try:
name = str(expo.name)
except UnicodeEncodeError, UnicodeDecodeError:
name = expo.url
alt = u'%s_%s'%(name, role)
return self.create(alt=alt, url=url, paid=True)
class BannerGroupCached(models.Manager):
def all(self):
key = 'banner_group_all'
result = cache.get(key)
if not result:
result = list(self.filter(public=True))
cache.set(key, result, 90)
return result
def group_banners(self):
key = 'banner_group_banners'
result = cache.get(key)
if not result:
groups = self.all()
today = date.today()
result = {}
for group in groups:
result[group.slug] = list(group.banners.prefetch_related('urls', 'theme', 'country')\
.filter(public=True, fr__lte=today)\
.filter(Q(to__gte=today) | Q(to__isnull=True)).extra({}))
cache.set(key, result, 70)
return result
class URLCached(models.Manager):
def all(self):
key = 'banner_url_all'
result = cache.get(key)
if not result:
result = list(self.filter(public=True))
cache.set(key, result, 150)
return result
class TopCached(models.Manager):
def all(self):
key = 'expo_b_top_all'
result = cache.get(key)
if not result:
result = list(self.prefetch_related('theme', 'country', 'excluded_tags', 'excluded_cities').all())
cache.set(key, result, 80)
return result

@ -0,0 +1,3 @@
class StatMixin(object):
def get_cookie_name(self):
return u'%s_%d'%(self._meta.db_table, self.id)

@ -0,0 +1,294 @@
# -*- coding: utf-8 -*-
import random
import hashlib
from datetime import datetime, date
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.contrib.sites.models import Site
from django.db.models.signals import post_save
from .managers import BiasedManager, BannerGroupCached, URLCached, TopCached
from .mixins import StatMixin
from theme.models import Theme
from country.models import Country
class URL(models.Model):
title = models.CharField(verbose_name=u'Заголовок', max_length=256)
url = models.CharField(verbose_name=u'URL or URL RegEx', max_length=2048)
regex = models.BooleanField(verbose_name=u'RegEx', default=False)
sites = models.ManyToManyField(Site, related_name='site_urls', verbose_name=_('Sites'), null=True, blank=True)
public = models.BooleanField(verbose_name=u'Активный', default=True)
created_at = models.DateTimeField(verbose_name=_('Created At'), auto_now_add=True)
updated_at = models.DateTimeField(verbose_name=_('Updated At'), auto_now=True)
objects = models.Manager()
cached = URLCached()
def __unicode__(self):
return self.title
class Meta:
ordering = ['-created_at']
verbose_name = _('URL')
verbose_name_plural = _('URLs')
def get_admin_url(self):
return '/admin/expobanners/banners/url/%d/edit/'%self.id
class BannerGroup (models.Model):
name = models.CharField(verbose_name=u'Имя', max_length=255)
slug = models.SlugField(verbose_name=u'URL', unique=True)
width = models.PositiveSmallIntegerField(verbose_name=u'Ширина', default=0)
height = models.PositiveSmallIntegerField(verbose_name=u'Высота', default=0)
speed = models.PositiveSmallIntegerField(verbose_name=u'Скорость отображения', default=2000)
public = models.BooleanField(verbose_name=u'Активная', default=True)
created_at = models.DateTimeField(verbose_name=_('Created At'), auto_now_add=True)
updated_at = models.DateTimeField(verbose_name=_('Updated At'), auto_now=True)
objects = models.Manager()
cached = BannerGroupCached()
def size(self):
return '%sx%s' % (self.width, self.height)
def __unicode__(self):
return '%s - [%s x %s]' % (self.name, self.width, self.height)
class Meta:
ordering = ['name']
verbose_name = _('Banner Group')
verbose_name_plural = _('Banner Groups')
def get_admin_url(self):
return '/admin/expobanners/banners/group/%d/edit/'%self.id
class Banner(models.Model, StatMixin):
objects = BiasedManager()
title = models.CharField(verbose_name=u'Заголовок', max_length=255, blank=True)
alt = models.CharField(verbose_name=_('Alt'), max_length=255)
text = models.TextField(verbose_name=u'Текст', blank=True, null=True)
img = models.FileField(verbose_name=u'Картинка', upload_to='expo_upload', blank=True, null=True)
url = models.CharField(verbose_name=u'URL', max_length=1024)
fr = models.DateField(default=date.today())
to = models.DateField(blank=True, null=True)
theme = models.ManyToManyField(Theme, blank=True, null=True, verbose_name=u'Тематика')
country = models.ManyToManyField(Country, blank=True, null=True, verbose_name=u'Страна')
sort = models.PositiveSmallIntegerField(verbose_name=u'Сорт', default=500)
group = models.ForeignKey(BannerGroup, related_name='banners', verbose_name=u'Место', null=True, blank=True)
often = models.PositiveSmallIntegerField(
verbose_name=_('Often'),
help_text=_('A ten will display 10 times more often that a one.'),
choices=[[i, i] for i in range(11)],
default=1
)
urls = models.ManyToManyField(URL, related_name='url_banners', verbose_name=_('URLs'), null=True, blank=True)
html = models.BooleanField(verbose_name=_('HTML?'), default=False)
flash = models.BooleanField(verbose_name=_('Flash?'), default=False)
js = models.BooleanField(verbose_name=_('Javascript?'), default=False)
paid = models.BooleanField(verbose_name=_('Is Paid event link?'), default=False)
public = models.BooleanField(verbose_name=u'Активный', default=True)
created_at = models.DateTimeField(verbose_name=_('Created At'), auto_now_add=True)
updated_at = models.DateTimeField(verbose_name=_('Updated At'), auto_now=True)
stat_pswd = models.CharField(max_length=16)
class Meta:
ordering = ['-public']
def get_admin_url(self):
return '/admin/expobanners/banners/banner/%d/edit/'%self.id
def key(slef):
if hasattr(settings, 'SECRET_KEY'):
key = str(datetime.now()) + settings.SECRET_KEY
else:
key = str(datetime.now())
return hashlib.md5(key).hexdigest()
def log(self, request, type):
log = {
'type': type,
'banner': self,
'group': self.group,
'ip': request.META.get('REMOTE_ADDR'),
'user_agent': request.META.get('HTTP_USER_AGENT'),
'page': request.META.get('HTTP_REFERER'),
}
if request.user.is_authenticated():
log['user'] = request.user
return Log.objects.create(**log)
@models.permalink
def image(self):
return ('banner_view', (), {'banner_id': self.pk, 'key': self.key()})
def impressions(self):
return Log.objects.filter(banner=self.pk, type=0).count()
def views(self):
return Log.objects.filter(banner=self.pk, type=1).count()
def clicks(self):
return Log.objects.filter(banner=self.pk, type=2).count()
def __unicode__(self):
return self.title or self.alt
def get_absolute_url(self):
if self.url == '#':
return self.url
else:
@models.permalink
def get_absolute_url(self):
return ('banner_click', (), {'banner_id': self.pk, 'key': self.key()})
return get_absolute_url(self)
def get_click_link(self):
return '/expo-b/click/%d/'%self.id
class Meta:
ordering = ['sort']
verbose_name = _('Banner')
verbose_name_plural = _('Banners')
class Log(models.Model):
banner = models.ForeignKey(Banner, related_name='banner_logs')
group = models.ForeignKey(BannerGroup, related_name='group_logs', verbose_name=_('Group'), blank=True, null=True)
urls = models.ManyToManyField(URL, related_name='url_logs', verbose_name=_('URLs'), blank=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name='users', verbose_name=_('User'))
datetime = models.DateTimeField(verbose_name=_('Clicked At'), auto_now_add=True)
ip = models.IPAddressField(verbose_name=_('IP'), null=True, blank=True)
user_agent = models.CharField(verbose_name=_('User Agent'), max_length=1024, null=True, blank=True)
page = models.URLField(verbose_name=_('Page'), null=True, blank=True)
key = models.CharField(verbose_name=_('User Agent'), max_length=32, null=True, blank=True)
TYPE_CHOICES = (
(0, 'impressions'),
(1, 'view'),
(2, 'click')
)
type = models.PositiveSmallIntegerField(verbose_name=_('Type'), max_length=1, default=0, choices=TYPE_CHOICES)
def __unicode__(self):
return '%s - (%s)' % (self.banner, self.datetime)
class LogStat(models.Model):
banner = models.ForeignKey(Banner, related_name='banner_stat', verbose_name=_('Banner'), blank=True)
group = models.ForeignKey(BannerGroup, related_name='group_stat', verbose_name=_('Group'), blank=True, null=True)
urls = models.ManyToManyField(URL, related_name='url_bloks', verbose_name=_('URLs'), null=True, blank=True)
date = models.DateField(verbose_name=_('Data'))
view = models.PositiveIntegerField(verbose_name=_('Views'))
click = models.PositiveIntegerField(verbose_name=_('Clicks'))
unique_click = models.PositiveIntegerField(verbose_name=_('Unique Views'), blank=True, null=True)
unique_view = models.PositiveIntegerField(verbose_name=_('Unique Clicks'))
def __unicode__(self):
return '%s - (%s)' % (self.banner, self.date)
# ------------------
class Paid(models.Model, StatMixin):
tickets = models.ForeignKey(Banner, related_name='paid_tickets')
participation = models.ForeignKey(Banner, related_name='paid_participation')
official = models.ForeignKey(Banner, related_name='paid_official')
catalog = models.ForeignKey(Banner, related_name='paid_catalog')
logo = models.ImageField(upload_to='expo-b/paid', blank=True)
organiser = models.CharField(max_length=100, blank=True)
public = models.BooleanField(default=True, verbose_name=u'Активная')
stat_pswd = models.CharField(max_length=16)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-public']
def get_event(self):
if self.exposition_set.all().exists():
return self.exposition_set.all()[0]
return None
class PaidStat(models.Model):
paid = models.ForeignKey(Paid)
date = models.DateField(verbose_name=_('Date'))
page_views = models.PositiveIntegerField(default=0)
price_views = models.PositiveIntegerField(default=0)
catalog_views = models.PositiveIntegerField(default=0)
catalog_clicks = models.PositiveIntegerField(default=0)
tickets_clicks = models.PositiveIntegerField(default=0)
participation_clicks = models.PositiveIntegerField(default=0)
official_clicks = models.PositiveIntegerField(default=0)
class Top(models.Model, StatMixin):
catalog = models.CharField(max_length=16, verbose_name=u'Каталог для топа')
position = models.PositiveIntegerField(blank=True, default=2, null=True, verbose_name=u'Позиция')
theme = models.ManyToManyField('theme.Theme', blank=True, null=True, verbose_name=u'Тематики')
excluded_tags = models.ManyToManyField('theme.Tag', blank=True, null=True, verbose_name=u'Исключить теги')
country = models.ManyToManyField('country.Country', blank=True, null=True, verbose_name=u'Страны')
excluded_cities = models.ManyToManyField('city.City', blank=True, null=True, verbose_name=u'Исключить города')
fr = models.DateField(default=date.today(), verbose_name=u'Начало')
to = models.DateField(blank=True, null=True, verbose_name=u'Конец')
stat_pswd = models.CharField(max_length=16)
objects = models.Manager()
cached = TopCached()
class Meta:
ordering = ['position']
class TopStat(models.Model):
date = models.DateField()
theme = models.ForeignKey('theme.Theme', blank=True, null=True)
tag = models.ForeignKey('theme.Tag', blank=True, null=True)
country = models.ForeignKey('country.Country', blank=True, null=True)
city = models.ForeignKey('city.City', blank=True, null=True)
views = models.PositiveIntegerField(default=0)
clicks = models.PositiveIntegerField(default=0)
def generatePassword(length=5):
"""
generate random password
"""
SYMBOLS = [',', '.', '?', '!', '-', '+', '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A',
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '#']
PASSWORD_LENGTH = length
newPassword = []
for i in range(PASSWORD_LENGTH):
newPassword.append(SYMBOLS[random.randrange(0, len(SYMBOLS))])
return ''.join(newPassword)
def generate_stat_pass(sender, **kwargs):
obj = kwargs['instance']
if not obj.stat_pswd:
obj.stat_pswd = generatePassword()
obj.save()
post_save.connect(generate_stat_pass, sender=Banner)
post_save.connect(generate_stat_pass, sender=Paid)
post_save.connect(generate_stat_pass, sender=Top)

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
from django.http import HttpResponseRedirect
from django.views.generic import TemplateView, CreateView, ListView, UpdateView, DetailView
from django.views.generic.edit import FormMixin
from django.forms.util import ErrorList
from django.conf import settings
from django.core.urlresolvers import reverse
from expobanner.models import Banner, Paid
from expobanner.forms import ClientStatForm
class BannerStat(FormMixin, DetailView):
model = Banner
form_class = ClientStatForm
template_name = 'client/expobanners/banner_stat.html'
def get_success_url(self):
return reverse('banner_stat_client', kwargs={'pk': self.object.pk})
def get_context_data(self, **kwargs):
context = super(BannerStat, self).get_context_data(**kwargs)
obj = self.object
cookie_name = obj.get_cookie_name()
cookie = self.request.session.get(cookie_name)
if not cookie:
form = context.get('form')
# form in context if form invalid called
if not form:
context['form'] = self.get_form(self.form_class)
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form(self.form_class)
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
obj = self.object
success = form.check_pass(obj)
if success:
self.request.session[obj.get_cookie_name()] = 1
return HttpResponseRedirect(self.get_success_url())
else:
form.errors['stat_pswd'] = ErrorList([u'Неправильный пароль'])
return self.form_invalid(form)
class PaidStat(BannerStat):
model = Paid
template_name = 'client/expobanners/paid_stat.html'
def get_success_url(self):
return reverse('paid_stat_client', kwargs={'pk': self.object.pk})

@ -0,0 +1,159 @@
/*
**************************
* =COMMON
**************************
*/
.b-slider {
position: relative;
display: block;
overflow: hidden;
margin: 0;
padding: 0;
width: 725px;
height: 360px;
}
.b-slider-list {
position: absolute;
display: block;
overflow: hidden;
margin: 0;
padding: 0;
width: 725px;
height: 360px;
list-style: none;
}
.b-slider-item {
position: absolute;
z-index: 50;
float: left;
overflow: hidden;
margin: 0;
padding: 0;
width: 725px;
height: 360px;
}
.m-slider-current {
z-index: 100;
}
.b-slider-item__img,
.b-slider-item__title,
.b-slider-item__text {
position: absolute;
}
.b-slider-item__img {
top: 0;
left: 0;
text-decoration: none;
}
.b-slider-item__link {
}
.b-slider-item__title {
bottom: 10px;
left: 10px;
width: 500px;
color: #333;
text-transform: uppercase;
text-shadow: 0 0 3px #fff, 0 0 2px #fff, 0 0 1px #fff;
letter-spacing: -5px;
font-size: 65px;
font-family: Calibri;
line-height: 0.8em;
}
.b-slider-item__text {
position: absolute;
top: 150px;
left: 300px;
display: inline-block;
display: none;
margin: -10px;
padding: 10px;
max-width: 300px;
border-radius: 10px;
background: rgba(255, 255, 255, 0.5);
box-shadow: 0 0 5px #fff;
color: #555;
line-height: 1.5em;
}
/*
**************************
* =NAV
**************************
*/
.b-slider-nav {
position: absolute;
width: 100%;
top: 10px;
height: 30px;
left: 0;
z-index: 500;
display: block;
margin: 0;
padding: 0;
list-style-type: none;
text-align: center;
}
.b-slider-nav-button {
display: inline-block;
margin: 5px;
width: 16px;
height: 16px;
border-radius: 8px;
background: #ddd;
color: transparent;
text-align: center;
font-weight: bold;
font-size: 8px;
line-height: 16px;
cursor: pointer;
}
.b-slider-nav-button:hover {
background: #eee;
}
.m-slider-nav-current_button {
background: #fff;
}
.b-slider-nav-prev,
.b-slider-nav-next {
position: absolute;
top: 0;
z-index: 500;
padding-right: 20px;
padding-left: 20px;
color: #000;
text-shadow: 0 0 3px #fff, 0 0 2px #fff, 0 0 1px #fff;
font-size: 50px;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
line-height: 360px;
opacity: 0.5;
cursor: pointer;
}
.b-slider-nav-prev:hover,
.b-slider-nav-next:hover {
opacity: 0.8;
}
.b-slider-nav-prev {
left: 0;
padding-left: 0;
}
.b-slider-nav-next {
right: 0;
padding-right: 0;
}

@ -0,0 +1,10 @@
$(document).ready(function() {
$('.b-banner-click').on('click', function(){
$.get($(this).data('url'));
});
$(".b-banner").on('load', function() {
$.get($(this).data('view'));
});
});

@ -0,0 +1,71 @@
$.fn.bannersSlider = function(options) {
$this = this;
var settings = $.extend( {
'auto_play': false,
'effect': 'fade',
'speed' : 3000
}, options);
$this.current = 1;
$this.old = 1;
$this.len = $this.find('.b-slider-list li').length;
$this.find('.b-slider-item').hide();
$this.find('.m-slider-item-1').show();
$this.fadeTo = function(new_num) {
old_num = $this.old;
if (new_num != old_num) {
$this.find('.m-slider-item-' + new_num).hide();
$this.find('.m-slider-item-' + new_num).fadeIn(1000);
$this.find('.m-slider-current').fadeOut(1000);
$this.find('.m-slider-current').removeClass('m-slider-current');
$this.find('.m-slider-item-' + new_num).addClass('m-slider-current');
$this.find('.b-slider-nav-button').removeClass('m-slider-nav-current_button');
$this.find('.b-slider-nav-button[data-slide=' + new_num + ']').addClass('m-slider-nav-current_button');
}
};
$this.prev = function() {
prev = ($this.current != 1) ? $this.current - 1 : $this.len;
$this.old = $this.current;
$this.current = prev;
$this.fadeTo(prev);
};
$this.next = function() {
next = ($this.current != $this.len) ? $this.current + 1 : 1;
$this.old = $this.current;
$this.current = next;
$this.fadeTo(next);
};
$this.children('.b-slider-nav-prev').on('click', function(){
$this.prev();
});
$this.children('.b-slider-nav-next').on('click', function(){
$this.next();
});
$this.find('.b-slider-nav-button').on('click', function(){
to_slide = $(this).data('slide');
$this.old = $this.current;
$this.current = to_slide;
$this.fadeTo(to_slide);
});
if (settings.auto_play) {
setInterval(function() {
$this.next();
}, settings.speed);
}
return $this;
};

@ -0,0 +1,55 @@
{% if banner.html %}
{% load banner %}
<div id='banner_{{ banner.id }}' class='b-banner b-banner-{{ group.slug }} m-banner__html'>
{% render banner.text %}
</div>
{% elif banner.flash %}
<div id='banner_{{ banner.id }}' class='b-banner b-banner-{{ group.slug }} m-banner__flash'>
<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'
codebase='http://fpdownload.adobe.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0'
width='{{ banner.group.width }}' height='{{ banner.group.height }}'>
<param name='movie' value='{{ banner.img.url }}' />
<param name='quality' value='high'>
<param name='play' value='true'>
<param name='loop' value='true'>
<param name='wmode' value='transparent'>
<embed src='{{ banner.img.url }}'
quality='high'
bgcolor='#d0f'
width='{{ banner.group.width }}'
height='{{ banner.group.height }}'
name='banner_{{ banner.id }}'
type='application/x-shockwave-flash'
play='true'
loop='true'
wmode='transparent'
pluginspage='http://www.adobe.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash'
>
</embed>
</object>
</div>
<script>
$('#banner_{{ banner.id }}').mousedown(function() {
// alert('mouse down');
});
</script>
{% else %}
<a href='{{ banner.url }}' id='banner_{{ banner.id }}' class='b-banner b-banner-{{ group.slug }}'>
<img src='{{ banner.img.url }}' alt='{{ banner.alt }}' title='{{ banner.title }}'>
</a>
{% endif %}
<style>
.b-banner {
display: block;
padding: 0;
margin: 0;
/*border: 1px solid silver;*/
}
.b-banner-{{ group.slug }} {
width: {{ banner.group.width }}px;
height: {{ banner.group.height }}px;
}
</style>

@ -0,0 +1,32 @@
{% load banner %}
<div class="b-banner-group">
{% for banner in banners %}
{% banner_one banner.id %}
{% endfor %}
</div>
<style type="text/css">
.b-banner-group {
display: block;
overflow: hidden;
}
.b-banner {
display: block;
padding: 0;
margin: 0;
/*border: 1px solid silver;*/
}
.b-banner-{{ group.slug }} {
width: {{ banner.group.width }}px;
height: {{ banner.group.height }}px;
float: left;
}
.b-banner-{{ group.slug }} img {
width: 100%;
height: 100%;
}
</style>

@ -0,0 +1,30 @@
{% load banner %}
<div class="b-banner-group">
{% for banner in banners %}
{% banner_one banner.id %}
{% endfor %}
<script>
var arr = [];
{% for banner in banners %}
arr[{{ forloop.counter }}] = {'id': {{ banner.id }}, 'often': {{ banner.often }}};
{% endfor %}
var length = arr.length - 1;
var i = 1;
var speed = {{ group.speed }};
$('.b-banner-{{ group.slug }}').hide();
$('#banner_' + arr[i]['id']).show();
total_speed = speed * arr[i]['often'];
setInterval(function () {
if (i < length) i++; else i = 1;
total_speed = speed * arr[i]['often'];
console.log (total_speed, arr[i]);
$('.b-banner-{{ group.slug }}').hide();
$('#banner_' + arr[i]['id']).show();
}, speed);
</script>
</div>

@ -0,0 +1,74 @@
{% load thumbnail %}
{% if banners %}
<div class="b-slider m-{{ group.slug }}" id="slider-{{ group.slug }}">
<ul class='b-slider-list'>
{% for banner in banners %}
<li data-url='{{ banner.get_absolute_url }}'
class='
b-slider-item
m-slider-item-{{ forloop.counter }}
{% if forloop.counter == 1 %}
m-slider-current
{% endif %}
'
data-slide='{{ forloop.counter }}'
>
<a href='{{ banner.get_absolute_url }}' class='b-slider-item__link'>
{% thumbnail banner.img group.size crop="top" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" alt="{{ banner.alt }}" title="{{ banner.title }}" class='b-slider-item__img' data-view='{{ banner.image }}'>
{% endthumbnail %}
<div class="b-slider-item__info_cover">
<span class='b-slider-item__title'>{{ banner.title|safe }}</span>
<span class='b-slider-item__text'>{{ banner.text|safe }}</span>
</div>
</a>
</li>
{% endfor %}
</ul>
<ul class="b-slider-nav">
{% for banner in banners %}
<li class="b-slider-nav-button
{% if forloop.counter == 1 %}
m-slider-nav-current_button
{% endif %}
" data-slide='{{ forloop.counter }}'>
{{ forloop.counter }}
</li>
{% endfor %}
</ul>
<span data-direction="prev" class='b-slider-nav-prev'>&#9001;&nbsp;&nbsp;</span>
<span data-direction="next" class='b-slider-nav-next'>&nbsp;&nbsp;&#9002;</span>
</div>
<script>
(function() {
$('.m-{{ group.slug }}').bannersSlider({'auto_play': {{ group.speed }}, 'speed': {{ group.speed }}});
})();
</script>
<style>
.m-{{ group.slug }} {
width: {{ group.width }}px;
height: {{ group.height }}px;
}
.m-{{ group.slug }} .b-slider-nav-prev,
.m-{{ group.slug }} .b-slider-nav-next {
line-height: {{ group.height }}px;
}
.m-{{ group.slug }} .b-slider-item,
.m-{{ group.slug }} .b-slider-list {
width: {{ group.width }}px;
height: {{ group.height }}px;
}
</style>
{% endif %}

@ -0,0 +1,74 @@
from ..models import Banner
from ..models import BannerGroup
from ..models import URL
from django import template
# For render tag
from django.template import Context
from django.template import Template
import re
register = template.Library()
@register.simple_tag(takes_context=True)
def banner_group(context, group, tpl='group.html'):
try:
page_url = context['request'].path_info
site = context['request'].site
group = BannerGroup.objects.get(slug=group)
good_urls = []
for url in URL.objects.filter(public=True, sites__in=[site]):
if url.regex:
url_re = re.compile(url.url)
if url_re.findall(page_url):
good_urls.append(url)
elif page_url == url.url:
good_urls.append(url)
banners = Banner.objects.filter(public=True, group=group, urls__in=good_urls)
except:
banners = False
group = False
if(banners and group):
context['banners'] = banners
context['group'] = group
t = template.loader.get_template(tpl)
return t.render(template.Context(context))
@register.simple_tag(takes_context=True)
def banner_one(context, banner_id, tpl='banner.html'):
try:
page_url = context['request'].path_info
site = context['request'].site
good_urls = []
for url in URL.objects.filter(public=True, sites__in=[site]):
if url.regex:
url_re = re.compile(url.url)
if url_re.findall(page_url):
good_urls.append(url)
elif page_url == url.url:
good_urls.append(url)
banner = Banner.objects.get(id=banner_id, public=True, urls__in=good_urls)
except:
banner = False
context['banner'] = banner
t = template.loader.get_template(tpl)
return t.render(template.Context(context))
# block render
@register.simple_tag(takes_context=True)
def render(context, content):
try:
tpl = Template(content)
content = Context(context)
return tpl.render(content)
except:
return 'Render Error'

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

@ -0,0 +1,13 @@
from django.conf.urls import url
from expobanner.stat_views import *
from . import views
urlpatterns = [
url(r'^click/(?P<banner_id>\d{1,4})/$', views.click, name='banner_click'),
#url(r'^view/(?P<banner_id>\d+)/$', views.view, name='banner_view'),
#
url(r'^get-banners/$', views.get_banners),
url(r'^get-tops/$', views.get_top),
url(r'^banner/(?P<pk>\d+)/stat/$', BannerStat.as_view(), name='banner_stat_client'),
url(r'^paid/(?P<pk>\d+)/stat/$', PaidStat.as_view(), name='paid_stat_client'),
]

@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
import random
from django.db import connection
def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
def get_by_sort(banner_list):
max_sort = 0
for banner in banner_list:
sort = banner.sort
if sort > max_sort:
max_sort = sort
result = [banner for banner in banner_list if banner.sort == max_sort]
return result
def get_banner_by_params(banners_list, urls, params):
#print('START. NUMBER of queries = %d'%len(connection.queries))
thematic_banners = []
url_banners = []
for banner in banners_list:
#print('-------------------------')
#print('number of queries = %d'%len(connection.queries))
# check by theme
banner_theme_ids = [str(theme.id) for theme in banner.theme.all()]
#print('number of queries = %d'%len(connection.queries))
if banner_theme_ids:
if params.get('theme'):
theme = params['theme']
if theme in banner_theme_ids:
thematic_banners.append(banner)
continue
# check by country
banner_country_ids = [str(country.id) for country in banner.country.all()]
#print('number of queries = %d'%len(connection.queries))
if banner_country_ids:
if params.get('country'):
country = params['country']
if country in banner_country_ids:
thematic_banners.append(banner)
continue
# check by url
if urls:
banner_urls = banner.urls.all()
print('number of queries = %d'%len(connection.queries))
if banner_urls:
banner_urls = set(banner_urls)
common_urls = set(urls).intersection(banner_urls)
if common_urls:
url_banners.append(banner)
continue
print('-------------------------')
if thematic_banners:
return random.choice(thematic_banners)
if url_banners:
return random.choice(url_banners)
return None
#print('END. NUMBER of queries = %d'%len(connection.queries))

@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
import json
import re
from django.http import HttpResponse
from django.shortcuts import redirect, get_object_or_404
from .models import Banner, BannerGroup, URL, Top
from expobanner.utils import get_by_sort, get_banner_by_params, get_client_ip
def click(request, banner_id):
banner = get_object_or_404(Banner, pk=banner_id)
banner.log(request, 2)
return redirect(banner.url)
def view(request, banner_id):
banner = get_object_or_404(Banner, pk=banner_id)
banner.log(request, 1)
return redirect(banner.img.url)
def get_banners(request):
#url = request.GET.get('url', '/')
url = request.META.get('HTTP_REFERER', '/')
# get urls by current url
urls = URL.cached.all()
good_urls = []
for u in urls:
if u.regex:
url_re = re.compile(u.url)
if url_re.findall(url):
good_urls.append(u)
elif url == u.url:
good_urls.append(u)
# fill parameters dict
params = {'theme': request.GET.get('theme'),
'tag': request.GET.get('tag'),
'country': request.GET.get('country'),
'city': request.GET.get('city'),
'ip': get_client_ip(request)}
group_banners = BannerGroup.cached.group_banners()
result = []
# get banners for all groups
for group, banners in group_banners.iteritems():
banner = get_banner_by_params(banners, good_urls, params)
if banner:
if banner.js or banner.html:
text = banner.text
img = ''
alt = ''
is_img = False
else:
text = ''
img = banner.img.url
alt = banner.alt
is_img = True
result.append({'id': group,
'url': banner.get_click_link(),
'is_html': banner.html,
'is_flash': banner.flash,
'is_img': is_img,
'is_js': banner.js,
'img': img,
'alt': alt,
'text': text
})
# add view log
banner.log(request, 1)
return HttpResponse(json.dumps(result, indent=4), content_type='application/json')
def get_top_events(tops, params):
catalog = params.get('catalog')
country = params.get('country', '')
theme = params.get('theme', [])
good_tops = []
for top in tops:
if top.catalog != catalog:
continue
country_ids = [str(item.id) for item in top.country.all()]
if not country in country_ids:
continue
from exposition.models import Exposition
from django.shortcuts import render_to_response
from django.template import RequestContext
def get_top(request):
params = {'theme': request.GET.get('theme'),
'tag': request.GET.get('tag'),
'country': request.GET.get('country'),
'city': request.GET.get('city'),
'catalog': request.GET.get('catalog')}
tops = Top.cached.all()
events = get_top_events(tops, params)
expos = Exposition.objects.filter(top__isnull=False)
context = {'objects': expos}
return render_to_response('client/includes/exposition/expo_top.html', context, context_instance=RequestContext(request))

@ -155,6 +155,9 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin):
max_open_area = models.PositiveIntegerField(verbose_name='Максимальная цена открытой площади',
blank=True, null=True)
registration_payment = models.PositiveIntegerField(verbose_name='Регистрационный взнос', blank=True, null=True)
paid_new = models.ForeignKey('expobanner.Paid', blank=True, null=True, on_delete=models.SET_NULL)
top = models.ForeignKey('expobanner.Top', blank=True, null=True, on_delete=models.SET_NULL)
#set manager of this model(fisrt manager is default)
objects = ExpoManager()
enable = ClientManager()

@ -19,9 +19,9 @@ class ExpositionIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin):
content_auto = indexes.EdgeNgramField()
form_name = indexes.CharField()
# translated fields
name_en = indexes.CharField()
name_en = indexes.CharField()
name_ru = indexes.CharField()
catalog_name_en = indexes.CharField()
catalog_name_en = indexes.CharField()
catalog_name_ru = indexes.CharField()
def prepare_form_name(self, obj):

@ -151,6 +151,7 @@ class ExpoDetail(JitterCacheMixin, MetadataMixin, DetailView):
model = Exposition
slug_field = 'url'
template_name = 'client/exposition/exposition_detail.html'
queryset = Exposition.objects.language().select_related('place', 'city', 'country', 'paid_new')
def get_context_data(self, **kwargs):
context = super(ExpoDetail, self).get_context_data(**kwargs)
@ -167,6 +168,7 @@ class ExpositionPrice(MetadataMixin, DetailView):
model = Exposition
slug_field = 'url'
template_name = 'client/exposition/price.html'
queryset = Exposition.objects.language().select_related('place', 'city', 'country', 'paid_new')
@ -375,6 +377,11 @@ class ExpoCountryCatalog(ExpoCatalog):
qs = self.model.enable.upcoming().filter(country=country)
return qs
def get_context_data(self, **kwargs):
context = super(ExpoCountryCatalog, self).get_context_data(**kwargs)
context['country'] = str(self.kwargs['country'].id)
return context
class ExpoCityCatalog(ExpoCatalog):
catalog_url = '/expo/city/'
def get_filtered_qs(self):
@ -385,6 +392,10 @@ class ExpoCityCatalog(ExpoCatalog):
qs = self.model.enable.upcoming().filter(city=city)
self.filter_object = city
return qs
def get_context_data(self, **kwargs):
context = super(ExpoCityCatalog, self).get_context_data(**kwargs)
context['city'] = str(self.kwargs['city'].id)
return context
class ExpoThemeCatalog(ExpoCatalog):
@ -423,10 +434,11 @@ class ExpoThemeCatalog(ExpoCatalog):
def get_context_data(self, **kwargs):
context = super(ExpoThemeCatalog, self).get_context_data(**kwargs)
if self.country:
context['country'] = self.country
context['country'] = str(self.country.id)
if self.city:
context['city'] = self.city
context['city'] = str(self.city.id)
context['theme_for_filter'] = self.kwargs['theme']
context['themes'] = [str(self.kwargs['theme'].id)]
return context
@ -449,6 +461,8 @@ class ExpoTagCatalog(ExpoCatalog):
context = super(ExpoTagCatalog, self).get_context_data(**kwargs)
tag = self.kwargs['tag']
context['theme_for_filter'] = tag.theme
context['themes'] = [str(tag.theme.id)]
context['tag'] = str(self.kwargs['tag'].id)
return context

@ -34,6 +34,9 @@ class EventMixin(object):
url = '%s%s/'%(self.get_catalog_url(), self.url)
return url
def get_paid_catalog_url(self):
return self.paid_new.catalog.get_click_link()
def org_split(self):
if self.org:
return self.org.split(';')

@ -11,13 +11,13 @@ 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')
else:
return super(ExpoManager, self).language(get_language()).all().order_by('name')
"""
def safe_get(self, **kwargs):
model = self.model
try:

@ -1,41 +1,97 @@
from accounts.models import User
import random
import string
def random_pass():
digits = random.sample(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), 4)
chars = random.sample(string.lowercase[:], 4)
password = chars + digits
random.shuffle(password)
return ''.join(password)
def load_user(details, response, uid, *args, **kwargs):
if details.get('email'):
username = details.get('email')
else:
username = str(uid)
user = User.objects.safe_get(username=username)
def load_user(strategy, details, response, uid, *args, **kwargs):
user = None
if details.get('email'):
email = details.get('email')
user = User.objects.safe_get(email=email)
return {'user': user, 'is_new': False}
from django.contrib.sites.models import Site, RequestSite
from registration.models import RegistrationProfile
def create_user(strategy, details, response, uid, user=None, *args, **kwargs):
if user:
return {'user': user, 'is_new': False}
else:
request = strategy.request
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
new_user = RegistrationProfile.objects.create_inactive_user(details['first_name'], details['last_name'], details['email'],
random_pass(), site or 1)
signals.user_registered.send(sender=User, user=new_user, request=request)
#user = User.objects.create_social_user(username, details['first_name'], details['last_name'])
return {'user': new_user, 'is_new': True}
if details.get('email'):
username = details.get('email')
from django.shortcuts import redirect
from social.pipeline.partial import partial
from registration import signals
@partial
def require_email(strategy, details, user=None, is_new=False, *args, **kwargs):
if user and user.email:
return
elif is_new and not details.get('email'):
email = strategy.request_data().get('email')
if email:
details['email'] = email
else:
username = str(uid)
strategy.request.session['new_email'] = True
return redirect('acquire_email')
user = User.objects.create_social_user(username, details['first_name'], details['last_name'])
return {'user': user, 'is_new': True}
from django.core import signing
from django.core.mail import EmailMultiAlternatives
from django.conf import settings
from django.core.urlresolvers import reverse
def SendVerificationEmail(strategy, backend, code):
"""
if details.get('email'):
user = User.objects.safe_get(email=details['email'])
if user:
return {'user': user, 'is_new': False}
else:
user = User.objects.create_user(email=details['email'], first_name=details['first_name'],
last_name=details['last_name'], password='1q2w3e4r', is_active=True)
Send an email with an embedded verification code and the necessary details to restore the required session
elements to complete the verification and sign-in, regardless of what browser the user completes the
verification from.
"""
signature = signing.dumps({"session_key": strategy.session.session_key, "email": code.email},
key=settings.EMAIL_SECRET_KEY)
verifyURL = "{0}?verification_code={1}&signature={2}".format(
reverse('social:complete', args=(backend.name,)),
code.code, signature)
verifyURL = strategy.request.build_absolute_uri(verifyURL)
return {'user': user, 'is_new': True}
else:
return None
"""
emailHTML = ''# Include your function that returns an html string here
emailText = """Welcome to Expomap.ru!
In order to login with your new user account, you need to verify your email address with us.
Please click on <a href='{verifyURL}'>this link</a> to continue registration.
""".format(verifyURL=verifyURL)
kwargs = {
"subject": "Verify Your Account",
"body": emailText,
"from_email": settings.CALLBACK_EMAIL,
"to": [code.email],
}
email = EmailMultiAlternatives(**kwargs)
email.attach_alternative(emailHTML, "text/html")
email.send()

@ -239,7 +239,6 @@ class ExpositionSearchForm(AbstactSearchForm):
required=False, widget=forms.CheckboxSelectMultiple())
tg = forms.CharField(label=_(u'Теги'), required=False, widget=forms.CheckboxSelectMultiple())
#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.language().all()],

@ -65,12 +65,12 @@ def to_country(value):
return None
def to_city(value, lang, country):
try:
# get city by name
#objects = get_translation_aware_manager(City)
# except IndexError if no found
city = City.objects.filter(translations__name=value, country=country)[0]
# print(city)
return city.id
except IndexError:
print('---------city error------------')
@ -173,7 +173,6 @@ def save_logo(obj, path):
full_path = settings.MEDIA_ROOT + logo_path
try:
alt_name = get_alternative_filename(full_path, file_name)
except UnicodeEncodeError:

@ -1,9 +1,14 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from admin import MetaListView, MetaView
from .views import CreateSeoText, SeoTextList, EditSeoText, DeleteSeoText
urlpatterns = patterns('conference.admin',
url(r'^seo/new/$', CreateSeoText.as_view(), name='seo_new'),
url(r'^seo/all/$', SeoTextList.as_view(), name='seo_all'),
url(r'^seo/edit/(?P<pk>\d{1,5})/$', EditSeoText.as_view(), name='seo_edit'),
url(r'^seo/delete/(?P<pk>\d{1,5})/$', DeleteSeoText.as_view(), name='seo_delete'),
url(r'^all/$', MetaListView.as_view()),
#url(r'^change/(?P<url>.*)/$', 'conference_change'),
url(r'^(?P<id>.*)/$', MetaView.as_view()),

@ -45,4 +45,16 @@ class MetaForm(forms.Form):
meta.save()
class MetaFilterForm(AdminFilterForm):
model = MetaSetting
model = MetaSetting
from .models import SeoText
from ckeditor.widgets import CKEditorWidget
from hvad.forms import TranslatableModelForm
class SeoTextForm(TranslatableModelForm):
class Meta:
model = SeoText
fields = ['url', 'title', 'body']
widgets = {'body':CKEditorWidget}

@ -113,4 +113,67 @@ class MetaSetting(TranslatableModel):
return []
post_save.connect(post_save_handler, sender=MetaSetting)
post_save.connect(post_save_handler, sender=MetaSetting)
# SEO - tests #
from django.db import models
from hvad.models import TranslatableModel, TranslatedFields
from django.conf import settings
from django.core.urlresolvers import reverse_lazy
from django.core.cache import cache
class SeoTextManager(TranslationManager):
cache_time = 120
def cache_get(self, *args, **kwargs):
url = kwargs.get('url')
lang = kwargs.get('lang')[:2] or translation.get_language()[:2]
key = 'seo_text_cache'
result = cache.get(key)
if result:
return result.get(lang+'_' + url)
qs = list(SeoText.objects.language('all'))
value_dict = {obj.language_code+'_'+obj.url:obj for obj in qs}
cache.set(key, value_dict, self.cache_time)
return value_dict.get(lang+'_'+url)
class SeoText(TranslatableModel):
url = models.CharField(max_length=50, unique=True)
translations = TranslatedFields(
title=models.CharField(max_length=255),
body=models.TextField()
)
objects = SeoTextManager()
def get_absolute_url(self):
return reverse_lazy('seo_all')
def save(self, *args, **kwargs):
super(SeoText,self).save(*args, **kwargs)
all_field_names = list(self._translated_field_names)
clear_f_n = []
for field_name in all_field_names:
if field_name not in ['master', 'master_id', u'id', 'language_code']:
clear_f_n.append(field_name)
field_items = {field_name:getattr(self, field_name) for field_name in clear_f_n}
langs = [lan[0] for lan in settings.LANGUAGES]
for lang in langs:
if lang not in self.get_available_languages():
self.translate(lang)
for field in clear_f_n:
setattr(self, field, field_items.get(field, ''))
super(SeoText,self).save(*args, **kwargs)
return SeoText
def __unicode__(self):
return self.url

@ -187,4 +187,49 @@ class MetadataMixin(object):
site_name=self.get_meta_site_name(context=context),
)
return context
return context
from django.views.generic import CreateView, UpdateView, DeleteView, ListView
from .models import SeoText
from .forms import SeoTextForm
class CreateSeoText(CreateView):
form_class = SeoTextForm
model = SeoText
template_name = "admin/meta/create_seo_text.html"
success_url = '/admin/meta/seo/all/'
class SeoTextList(ListView):
model = SeoText
template_name = "admin/meta/seo_admin_list.html"
class EditSeoText(UpdateView):
form_class = SeoTextForm
model = SeoText
template_name = "admin/meta/create_seo_text.html"
class DeleteSeoText(DeleteView):
model = SeoText
template_name = "admin/meta/seo_confirm_delete.html"
success_url = '/admin/meta/seo/all/'

@ -12,12 +12,14 @@ urlpatterns = required(
url(r'^$', AdminIndex.as_view()),
url(r'^', include('import_xls.admin_urls')),
url(r'^accounts/', include('accounts.admin_urls')),
url(r'page/', include('core.admin_urls')),
url(r'^article/', include('article.admin_urls')),
url(r'^photogallery/', include('photologue.admin_urls')),
url(r'^city/', include('city.admin_urls')),
url(r'^company/', include('company.admin_urls')),
url(r'^conference/', include('conference.admin_urls')),
url(r'^country/', include('country.admin_urls')),
url(r'^expobanners/', include('expobanner.admin_urls')),
url(r'^exposition/', include('exposition.admin_urls')),
url(r'^news/', include('news.admin_urls')),
url(r'^organiser/', include('organiser.admin_urls')),

@ -0,0 +1,16 @@
from functools import wraps
from django.template import RequestContext
from django.shortcuts import render_to_response
def render_to(tpl):
def decorator(func):
@wraps(func)
def wrapper(request, *args, **kwargs):
out = func(request, *args, **kwargs)
if isinstance(out, dict):
out = render_to_response(tpl, out, RequestContext(request))
return out
return wrapper
return decorator

@ -42,7 +42,7 @@ CACHES = {
# 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 = ['hit.expomap.ru', '195.66.79.152', '195.66.79.145', 'expomap.ru']
ALLOWED_HOSTS = ['hit.expomap.ru', '195.66.79.152', '195.66.79.145', 'expomap.ru', '195.66.79.148']
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
@ -108,7 +108,7 @@ STATIC_URL = '/static/'
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
#'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
# Make this unique, and don't share it with anybody.
@ -173,6 +173,7 @@ TEMPLATE_DIRS = (
os.path.join(SITE_ROOT, 'templates/admin/organiser'),
os.path.join(SITE_ROOT, 'templates/admin/place_conference'),
os.path.join(SITE_ROOT, 'templates/admin/place_exposition'),
os.path.join(SITE_ROOT, 'templates/admin/page'),
os.path.join(SITE_ROOT, 'templates/admin/photoreport'),
os.path.join(SITE_ROOT, 'templates/admin/settings'),
os.path.join(SITE_ROOT, 'templates/admin/seminar'),
@ -198,12 +199,13 @@ EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
EMAIL_USE_TLS = True
EMAIL_PORT = 25
DEFAULT_FROM_EMAIL = "expomap.ru"
AUTHENTICATION_BACKENDS = (
'social.backends.open_id.OpenIdAuth',
'social.backends.vk.VKOAuth2',
'social.backends.facebook.FacebookOAuth2',
'social.backends.twitter.TwitterOAuth',
@ -216,14 +218,31 @@ AUTHENTICATION_BACKENDS = (
SOCIAL_AUTH_LOGIN_URL = '/'
SOCIAL_AUTH_USER_MODEL = 'accounts.User'
#SOCIAL_AUTH_UID_LENGTH = <int>
#SOCIAL_AUTH_NONCE_SERVER_URL_LENGTH = <int>
#SOCIAL_AUTH_ASSOCIATION_SERVER_URL_LENGTH = <int>
#SOCIAL_AUTH_FORCE_EMAIL_VALIDATION = True
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/logged-in/'
# The user will be redirected to this URL when a social account is disconnected
SOCIAL_AUTH_INACTIVE_USER_URL = '/inactive-user/'
# #Used to redirect the user once the auth process ended successfully. The value of ?next=/foo is used if it was present
# SOCIAL_AUTH_LOGIN_ERROR_URL = '/login-error/'
# #URL where the user will be redirected in case of an error
# SOCIAL_AUTH_LOGIN_URL = '/login-url/'
# #Is used as a fallback for LOGIN_ERROR_URL
# SOCIAL_AUTH_NEW_USER_REDIRECT_URL = '/new-users-redirect-url/'
# # Used to redirect new registered users, will be used in place of SOCIAL_AUTH_LOGIN_REDIRECT_URL if defined.
# Note that ?next=/foo is appended if present, if you want new users to go to next, you’ll need to do it yourself.
# SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = '/new-association-redirect-url/'
# # Like SOCIAL_AUTH_NEW_USER_REDIRECT_URL but for new associated accounts (user is already logged in).
# Used in place of SOCIAL_AUTH_LOGIN_REDIRECT_URL
# SOCIAL_AUTH_DISCONNECT_REDIRECT_URL = '/account-disconnected-redirect-url/'
# Inactive users can be redirected to this URL when trying to authenticate.
# SOCIAL_AUTH_UID_LENGTH = <int>
# SOCIAL_AUTH_NONCE_SERVER_URL_LENGTH = <int>
# SOCIAL_AUTH_ASSOCIATION_SERVER_URL_LENGTH = <int>
# SOCIAL_AUTH_FORCE_EMAIL_VALIDATION = True
SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
#SOCIAL_AUTH_STORAGE = 'social.apps.django_app.me.models.DjangoStorage'
from social.pipeline.social_auth import social_details
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
@ -231,35 +250,53 @@ SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'functions.pipeline.require_email',
#'social.pipeline.mail.mail_validation',
'functions.pipeline.create_user',
#'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_by_email',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'
)
REQUIRES_EMAIL_VALIDATION = True
SOCIAL_AUTH_EMAIL_VALIDATION_FUNCTION = 'functions.pipeline.SendVerificationEmail'
SOCIAL_AUTH_EMAIL_VALIDATION_URL = '/email_verify_sent/'
SOCIAL_AUTH_VK_OAUTH2_KEY = '3393841'
SOCIAL_AUTH_VK_OAUTH2_SECRET = '2P19EBUEpLZifaabbREv'
SOCIAL_AUTH_VK_OAUTH2_SCOPE =['email']
SOCIAL_AUTH_VK_OAUTH2_PROFILE_EXTRA_PARAMS = {
'fields': 'email'
}
SOCIAL_AUTH_FACEBOOK_KEY = '133775720059470'
SOCIAL_AUTH_FACEBOOK_SECRET = '434edf89c24a290497646a739df656c6'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', 'publish_actions']
SOCIAL_AUTH_TWITTER_KEY = 'S6NX33FazTcWuqnXQhlOdg'
SOCIAL_AUTH_TWITTER_SECRET = 'MxUGfySQmLI5kvqSoAtWsGje2eAHQL7Jo8mXuIZ4D0'
SOCIAL_AUTH_TWITTER_SCOPE = ['email']
SOCIAL_AUTH_GOOGLE_OAUTH_KEY = '1044044901114.apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH_SECRET = 'j_McErlPPof88eNrmOXI-ZXI'
SOCIAL_AUTH_GOOGLE_OAUTH_SCOPE = ['email']
SOCIAL_AUTH_MAILRU_OAUTH2_KEY = '697945'
SOCIAL_AUTH_MAILRU_OAUTH2_SECRET = '343581b9e31961b334532cc1880066e8'
SOCIAL_AUTH_MAILRU_OAUTH2_SCOPE = ['email']
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_KEY = 'CBAQDCKIABABABABA'
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_SECRET = '814CDDCD3E2D2F278EF1591B'
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_PUBLIC_NAME = '128007936'
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_PUBLIC_SCOPE = ['email']
SOCIAL_AUTH_LINKEDIN_KEY = 'jt9xwquj1fkd'
SOCIAL_AUTH_LINKEDIN_SECRET = 'GvM2xQCNADaBfiMy'
SOCIAL_AUTH_LINKEDIN_SCOPE = ['email']
@ -282,6 +319,7 @@ INSTALLED_APPS = (
'core',
'country',
'directories',
'expobanner',
'exposition',
'file',
'import_xls',
@ -314,8 +352,8 @@ INSTALLED_APPS = (
'pytils', # ??
'pymorphy', # ??
'password_reset', # reset password
'django_crontab', # crons
'social.apps.django_app.default', # social auth
'core',
)
@ -363,15 +401,21 @@ LOGGING = {
}
}
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']),
]
# TODO automate crons
"""
# update search indexes
0 * * * * /usr/bin/python /var/www/proj/manage.py update_index conference --remove --age=6
0 * * * * /usr/bin/python /var/www/proj/manage.py update_index exposition --remove --age=6
0 1,13 * * * /usr/bin/python /var/www/proj/manage.py update_index place_exposition --remove --age=24
0 3 * * * /usr/bin/python /var/www/proj/manage.py update_index company --remove --age=48
0 4 * * * /usr/bin/python /var/www/proj/manage.py update_index theme --remove --age=48
0 5 * * * /usr/bin/python /var/www/proj/manage.py update_index tag --remove --age=48
0 6 * * * /usr/bin/python /var/www/proj/manage.py update_index country --remove --age=48
0 7 * * * /usr/bin/python /var/www/proj/manage.py update_index city --remove --age=48
# update banner logs
10 * * * * /usr/bin/python /var/www/proj/manage.py banner_log_update
20 2,14 * * * /usr/bin/python /var/www/proj/manage.py banner_log_check_previous_day
"""
THUMBNAIL_DEBUG = DEBUG

@ -43,6 +43,7 @@ urlpatterns = patterns('',
url(r'^theme/', include('theme.urls')),
url(r'^places/', include('place_exposition.urls')),
url(r'^translators/', include('translator.urls')),
url(r'^expo-b/', include('expobanner.urls')),
url(r'^', include('accounts.urls')),
url(r'^', include('exposition.urls')),
url(r'^', include('settings.conference_old_urls')), # conference redirects from old version

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from django.core.context_processors import csrf
from django.shortcuts import render_to_response
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.generic import TemplateView
from django.conf import settings
@ -14,24 +14,53 @@ from functions.forms import ThemeSearch, PlaceSearch
from functions.search_forms import EventSearchForm, ExpositionSearchForm
from functions.custom_views import ExpoListView
from accounts.forms import RegistrationCompleteForm
from accounts.forms import RegistrationCompleteForm, SocialRegistrationCompleteForm
from meta.models import SeoText
from django.utils.translation import get_language
def clear_slashes(str_):
if str_[0] == r'/':
str_ = str_[1:]
if str_[-1] == r'/':
str_ = str_[:-1]
return str_
def add_seo(request):
url = request.path
lang = get_language()
try:
seo_text = SeoText.objects.cache_get(url=url, lang=lang)
except SeoText.DoesNotExist:
try:
seo_text = SeoText.objects.cache_get(url=url[:-1], lang=lang)
except SeoText.DoesNotExist:
seo_text = None
return seo_text
def expo_context(request):
banners_themes = [24, 34, 4]
banner_tags = [141, 142, 143, 156, 206, 231, 232, 390, 391, 400, 457, 500, 536, 537, 539, 457, 500, 686, 715, 765, 766, 857, 927, 964, 971, 972, 987, 1009, 1010, 1021, 2508, 2509, 2516, 2518, 2536, 2568, 2583, 2585, 3811, 3940, 4130, 4192, 4236, 4512, 4841, 5353, 5532, 5854, 106, 107, 195, 380, 930, 931, 932, 3845, 3846, 3863, 3873, 4141, 4142, 4343, 4344, 4347, 211, 212, 277, 631]
banner_tags = [141, 142, 143, 156, 206, 231, 232, 390, 391, 400, 457, 500, 536, 537, 539, 457, 500, 686, 715, 765,
766, 857, 927, 964, 971, 972, 987, 1009, 1010, 1021, 2508, 2509, 2516, 2518, 2536, 2568, 2583, 2585,
3811, 3940, 4130, 4192, 4236, 4512, 4841, 5353, 5532, 5854, 106, 107, 195, 380, 930, 931, 932, 3845,
3846, 3863, 3873, 4141, 4142, 4343, 4344, 4347, 211, 212, 277, 631]
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,
'banner_themes' : banners_themes, 'banner_tags' : banner_tags
'banner_themes': banners_themes, 'banner_tags': banner_tags, 'seo_text': add_seo(request)
}
user = request.user
if not user.is_anonymous() and not user.url:
cont.update({'reg_complete': RegistrationCompleteForm(instance=user)})
if not user.email:
cont.update({'reg_complete': SocialRegistrationCompleteForm(instance=user)})
else:
cont.update({'reg_complete': RegistrationCompleteForm(instance=user)})
if not request.GET:
cont.update({'search_form': ExpositionSearchForm()})
return cont
def error404(request):
context = {}
expo_themes = Theme.active.expo_themes_with_count()
@ -41,7 +70,8 @@ def error404(request):
response.status_code = 404
return response
class MainPageView(JitterCacheMixin,TemplateView):
class MainPageView(JitterCacheMixin, TemplateView):
cache_range = settings.CACHE_RANGE
template_name = 'index.html'
@ -63,5 +93,6 @@ class MainPageView(JitterCacheMixin,TemplateView):
class AdvertisingView(TemplateView):
template_name = 'simple_pages/advertising.html'
class AboutView(TemplateView):
template_name = 'simple_pages/about.html'
template_name = 'simple_pages/about.html'

@ -8,7 +8,7 @@ from registration import signals
from registration.models import RegistrationProfile
from registration.views import ActivationView as BaseActivationView
from registration.views import RegistrationView as BaseRegistrationView
from django.views.generic import View
import json
@ -150,7 +150,7 @@ from django.http import HttpResponse, HttpResponseRedirect
from accounts.models import User
from registration.forms import RegistrationFormUniqueEmail
from django.contrib.auth import login, logout
from django.contrib.auth import login, logout, authenticate
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.cache import never_cache
@ -248,15 +248,29 @@ def LoginView(request):
else:
HttpResponseRedirect('/')
from accounts.forms import RegistrationCompleteForm, RecoveryForm
from accounts.forms import RegistrationCompleteForm, RecoveryForm, SocialRegistrationCompleteForm
from social.apps.django_app.default.models import UserSocialAuth
def complete_registration(request):
if request.is_ajax():
response = {'success': False}
form = RegistrationCompleteForm(request.POST, instance=request.user)
if request.POST.get('email'):
form = SocialRegistrationCompleteForm(request.POST, instance=request.user)
else:
form = RegistrationCompleteForm(request.POST, instance=request.user)
if form.is_valid():
user = form.save()
response['success']=True
response['redirect'] = user.get_permanent_url()
if user != request.user:
try:
social = UserSocialAuth.objects.get(user=request.user)
uid, provider = social.uid, social.provider
User.objects.get(id = request.user.id).delete()
user.social_auth.create(uid=uid, provider=provider)
except UserSocialAuth.DoesNotExist:
pass
response['success']= True
response['redirect'] = '/'
else:
response['errors'] = form.errors
return HttpResponse(json.dumps(response), content_type='application/json')
@ -264,6 +278,22 @@ def complete_registration(request):
else:
return HttpResponse('not ajax')
from django.shortcuts import render
def acquire_email(request, template_name="registration/acquire_email.html"):
"""
Request email for the create user flow for logins that don't specify their email address.
"""
backend = request.session['partial_pipeline']['backend']
return render(request, template_name, {"backend": backend})
def inactive_user_message(request):
return render(request, 'registration/social_registration_complete.html')
def pswd_recovery(request):
#if request.is_ajax():
response = {'success': False}

@ -8,7 +8,7 @@ from city.models import City
CITIES = settings.MEDIA_ROOT+'/import/cities_inflect.xls'
TAGS = settings.MEDIA_ROOT+'/import/tags_inflect.xls'
import inspect, os
class Command(BaseCommand):
def handle(self, *args, **options):

@ -131,11 +131,9 @@ class Country_or_City(object):
result = 'city/%s'%obj.url
return {key: result}
old_params = {'city': CityRedirect, 'country': CountryRedirect, 'theme': ThemeRedirect, 'tag': TagRedirect,
'event': EventRedirect, 'company': Company, 'article': ArticleRedirect, 'user': UserRedirect,
'page': PageRedirect, 'news_p': News_p, 'country_or_city': Country_or_City}
'page': PageRedirect, 'news_p': News_p}
def old_redirect(request, *args, **kwargs):

@ -1,4 +1,4 @@
{% extends 'base.html' %}
{% extends 'base.html' %}
{% load static %}
{% block scripts %}
@ -23,8 +23,20 @@
}
});
return false;
});
$('#gen_pass').click(function(){
$('#id_new_password').val(generatePassword());
})
})
});
function generatePassword() {
var length = 8,
charset = "abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
retVal = "";
for (var i = 0, n = charset.length; i < length; ++i) {
retVal += charset.charAt(Math.floor(Math.random() * n));
}
return retVal;
}
</script>
<style>
.alert{
@ -120,6 +132,15 @@
<span class="help-inline">{{ form.position.errors }}</span>
</div>
</div>
{# position #}
<div class="control-group {% if form.new_password.errors %}error{% endif %}">
<label class="control-label">{{ form.new_password.label }}:</label>
<div class="controls">
{{ form.new_password }}
<a id="gen_pass" class="btn" href="javascript:void(0)">Generage password</a>
<span class="help-inline">{{ form.new_password.errors }}</span>
</div>
</div>
</div>
</div>
@ -161,11 +182,39 @@
</div>
</div>
{# social #}
<div class="control-group {% if form.social.errors %}error{% endif %}">
<label class="control-label">{{ form.social.label }}:</label>
<div class="control-group {% if form.skype.errors %}error{% endif %}">
<label class="control-label">{{ form.skype.label }}:</label>
<div class="controls">
{{ form.skype }}
<span class="help-inline">{{ form.skype.errors }}</span>
</div>
</div>
<div class="control-group {% if form.facebook.errors %}error{% endif %}">
<label class="control-label">{{ form.facebook.label }}:</label>
<div class="controls">
{{ form.facebook }}
<span class="help-inline">{{ form.facebook.errors }}</span>
</div>
</div>
<div class="control-group {% if form.linkedin.errors %}error{% endif %}">
<label class="control-label">{{ form.linkedin.label }}:</label>
<div class="controls">
{{ form.social }}
<span class="help-inline">{{ form.social.errors }}</span>
{{ form.linkedin }}
<span class="help-inline">{{ form.linkedin.errors }}</span>
</div>
</div>
<div class="control-group {% if form.twitter.errors %}error{% endif %}">
<label class="control-label">{{ form.twitter.label }}:</label>
<div class="controls">
{{ form.twitter }}
<span class="help-inline">{{ form.twitter.errors }}</span>
</div>
</div>
<div class="control-group {% if form.vk.errors %}error{% endif %}">
<label class="control-label">{{ form.vk.label }}:</label>
<div class="controls">
{{ form.vk }}
<span class="help-inline">{{ form.vk.errors }}</span>
</div>
</div>
{# company #}
@ -184,14 +233,7 @@
<span class="help-inline">{{ form.organiser.errors }}</span>
</div>
</div>
{# is_translator #}
<div class="control-group {% if form.is_translator.errors %}error{% endif %}">
<label class="control-label">{{ form.is_translator.label }}:</label>
<div class="controls">
{{ form.is_translator }}
<span class="help-inline">{{ form.is_translator.errors }}</span>
</div>
</div>
</div>
</div>
<div class="box span8">
@ -216,7 +258,7 @@
</div>
</div>
{# keywords #}
<d iv class="control-group {% if form.keywords.errors %}error{% endif %}">
<div class="control-group {% if form.keywords.errors %}error{% endif %}">
<label class="control-label">{{ form.keywords.label }}:</label>
<div class="controls">
{{ form.keywords }}
@ -227,7 +269,7 @@
</div>
<div class="controls">
<input class="btn btn-large btn-primary" type="submit" value="Добавить">
<input class="btn btn-large btn-primary" type="submit" value="Изменить">
<input class="btn btn-large" type="reset" value="Отмена">
</div>
</div>

@ -27,7 +27,6 @@
<th>Email</th>
<th>Полное имя</th>
<th>Админ</th>
<th>Переводчик</th>
<th>&nbsp;</th>
</tr>
</thead>
@ -43,12 +42,7 @@
{% else %}
<td>&nbsp;</td>
{% endif %}
{% if item.is_translator %}
<td>Да</td>
{% else %}
<td>&nbsp;</td>
{% endif %}
<td>&nbsp;</td>
<td class="center sorting_1">
<a class="btn btn-info" href="/admin/accounts/change/{% if item.url %}{{ item.url }}{% else %}{{ item.id }}{% endif %}">
<i class="icon-edit icon-white"></i> Изменить

@ -0,0 +1,36 @@
{% extends 'base.html' %}
{% block body %}
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-arrow-down"></i>{{ verbose }}</h2>
</div>
<div class="box-content">
{% block list_table %}
<table class="table table-hover">
<thead>
<tr>
<th>Объект</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for item in object_list %}
<tr>
<td>{{ item }}</td>
<td><a href="{{ item.get_admin_url }}">Изменить</a> </td>
<td><a href="{% url 'expobanner_stat_banner' item.id %}">Статистика</a> </td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
</div>
{# pagination #}
{% include 'admin/includes/admin_pagination.html' with page_obj=object_list %}
</div>
{% endblock %}

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% block scripts %}
<script src="{% static 'js/jquery.dataTables.min.js' %}"></script>
{% endblock %}
{% block body %}
<div class="row-fluid sortable">
<div class="box span12">
<div class="box-header well" data-original-title>
<h2><i class="icon-align-justify"></i> {{ object }} (Пароль: {{ object.stat_pswd }})</h2>
</div>
<div class="box-content">
<table class="table table-striped table-bordered bootstrap-datatable datatable">
<thead>
<tr>
<th>Дата</th>
<th>Показы</th>
<th>Клики</th>
<th>Уникальные показы</th>
<th>Уникальные клики</th>
</tr>
</thead>
<tbody>
{% with stats=object.banner_stat.all %}
{% for stat in stats %}
<tr>
<td>{{ stat.date|date:"Y-m-d" }}</td>
<td>{{ stat.view }}</td>
<td>{{ stat.click }}</td>
<td>{{ stat.unique_view }}</td>
<td>{{ stat.unique_click }}</td>
</tr>
{% endfor %}
{% endwith %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}

@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block body %}
<div class="row-fluid sortable ui-sortable">
<div class="box span6">
<div class="box-header well" data-original-title="">
<h2><i class="icon-th"></i> Создание</h2>
</div>
<div class="box-content">
<div class="row-fluid">
<div class="span4"><h6><a href="{% url 'expobanner-create_url' %}">Урла</a></h6></div>
<div class="span4"><h6><a href="{% url 'expobanner-create_group' %}">Групы</a></h6></div>
<div class="span4"><h6><a href="{% url 'expobanner-create_banner' %}">Банера</a></h6></div>
</div>
</div>
</div><!--/span-->
<div class="box span6">
<div class="box-header well" data-original-title="">
<h2><i class="icon-th"></i> Список</h2>
</div>
<div class="box-content">
<div class="row-fluid">
<div class="span4"><h6><a href="{% url 'expobanner-list_url' %}">Урлов</a></h6></div>
<div class="span4"><h6><a href="{% url 'expobanner-list_group' %}">Груп</a></h6></div>
<div class="span4"><h6><a href="{% url 'expobanner-list_banner' %}">Банеров</a></h6></div>
</div>
</div>
</div><!--/span-->
</div>
{% endblock %}

@ -0,0 +1,73 @@
{% extends 'base.html' %}
{% load static %}
{% block scripts %}
<link href="{% static 'js/select/select2.css' %}" rel="stylesheet"/>
<script src="{% static 'js/select/select2.js' %}"></script>
<script>
$(function(){
$('#id_fr').datetimepicker({
todayHighlight: true,
format : 'yyyy-mm-dd',
minView:2
});
$('#id_to').datetimepicker({
todayHighlight: true,
format : 'yyyy-mm-dd',
minView:2
});
$('#id_theme').select2({width: "element"});
$('#id_country').select2({width: "element"});
/*
$('#id_tag').select2({
placeholder: "Тег",
width: '200px',
ajax: {
url: "/admin/theme/tag/search-without-theme/",
dataType: "json",
quietMillis: 200,
multiple: true,
data: function(term, page){
return {term: term,
page: page};
},
results: function (data) {
return {results: data};
}
}
});
*/
})
</script>
{% endblock %}
{% block body %}
<form method="post" class="form-horizontal" name="form2" id="form2" enctype="multipart/form-data"> {% csrf_token %}
<fieldset>
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-pencil"></i>{{ form.verbose }}</h2>
</div>
<div class="box-content">
{% for field in form %}
<div class="control-group {% if field.errors %}error{% endif %}">
<label class="control-label">{% if field.field.required %}<b>{{ field.label }}:</b>{% else %}{{ field.label }}{% endif %}</label>
<div class="controls">{{ field }}
<span class="help-inline">{{ field.errors }}</span>
</div>
</div>
{% endfor %}
</div>
</div>
</fieldset>
<div class="controls">
<input class="btn btn-large btn-primary" type="submit" value="Готово">
<input class="btn btn-large" type="reset" value="Отмена">
</div>
</form>
{% endblock %}

@ -0,0 +1,34 @@
{% extends 'base.html' %}
{% block body %}
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-arrow-down"></i>{{ verbose }}</h2>
</div>
<div class="box-content">
{% block list_table %}
<table class="table table-hover">
<thead>
<tr>
<th>Объект</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for item in object_list %}
<tr>
<td>{{ item }}</td>
<td><a href="{{ item.get_admin_url }}">Изменить</a> </td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
</div>
{# pagination #}
{% include 'admin/includes/admin_pagination.html' with page_obj=object_list %}
</div>
{% endblock %}

@ -0,0 +1,71 @@
{% extends 'base.html' %}
{% load static %}
{% block scripts %}
{# selects #}
<link href="{% static 'js/select/select2.css' %}" rel="stylesheet"/>
<script src="{% static 'js/select/select2.js' %}"></script>
<script>
$(function(){
$('#id_exposition').select2({
placeholder: 'Найти',
width: 'element',
ajax: {
url: '/admin/exposition/search/',
dataType: "json",
quietMillis: 200,
multiple: true,
data: function(term, page, theme){
return {term: term,
page: page};
},
results: function (data) {
var results = [];
$.each(data, function(index, item){
results.push({
id: item.id,
text: item.label
});
});
return {results: results};
}
},
initSelection : function(element, callback) {
var id= $(element).val();
var text = $(element).attr('data-init-text');
callback({id: id, text:text});
}
});
});
</script>
{% endblock %}
{% block body %}
<form method="post" class="form-horizontal" name="form2" id="form2" enctype="multipart/form-data"> {% csrf_token %}
<fieldset>
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-pencil"></i>{{ form.verbose }}</h2>
</div>
<div class="box-content">
{% for field in form %}
<div class="control-group {% if field.errors %}error{% endif %}">
<label class="control-label">{% if field.field.required %}<b>{{ field.label }}:</b>{% else %}{{ field.label }}{% endif %}</label>
<div class="controls">{{ field }}
<span class="help-inline">{{ field.errors }}</span>
</div>
</div>
{% endfor %}
</div>
</div>
</fieldset>
<div class="controls">
<input class="btn btn-large btn-primary" type="submit" value="Готово">
<input class="btn btn-large" type="reset" value="Отмена">
</div>
</form>
{% endblock %}

@ -0,0 +1,38 @@
{% extends 'base.html' %}
{% block body %}
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-arrow-down"></i>Список проплаченых выставок</h2>
</div>
<div class="box-content">
{% block list_table %}
<a class="btn btn-success" href="{% url 'expobanner-create_paid' %}"><i class="icon-plus-sign icon-white"></i> Добавить выставку</a>
<table class="table table-hover">
<thead>
<tr>
<th>Выставка</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for item in object_list %}
<tr>
<td>{{ item }}</td>
<td><a href="{% url 'expobanner-update_paid' item.paid_new.id %}">Изменить</a> </td>
<td>{% if item.paid_new.public %}<a href="{% url 'expobanner-paid-turn' item.paid_new.id 'off' %}">отключить</a>{% else %}<a href="{% url 'expobanner-paid-turn' item.paid_new.id 'on' %}">включить</a>{% endif %} </td>
<td><a href="{% url 'expobanner_stat_paid' item.paid_new.id %}">Статистика</a> </td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
</div>
{# pagination #}
{% include 'admin/includes/admin_pagination.html' with page_obj=object_list %}
</div>
{% endblock %}

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% block scripts %}
<script src="{% static 'js/jquery.dataTables.min.js' %}"></script>
{% endblock %}
{% block body %}
<div class="row-fluid sortable">
<div class="box span12">
<div class="box-header well" data-original-title>
<h2><i class="icon-align-justify"></i> {{ object.get_event }} (Пароль: {{ object.stat_pswd }})</h2>
</div>
<div class="box-content">
<table class="table table-striped table-bordered bootstrap-datatable datatable">
<thead>
<tr>
<th>Дата</th>
<th>Официальный сайт</th>
<th>Билеты</th>
<th>Участие</th>
<th>Переходы с каталога</th>
</tr>
</thead>
<tbody>
{% with stats=object.paidstat_set.all %}
{% for stat in stats %}
<tr>
<td>{{ stat.date|date:"Y-m-d" }}</td>
<td>{{ stat.official_clicks }}</td>
<td>{{ stat.tickets_clicks }}</td>
<td>{{ stat.participation_clicks }}</td>
<td>{{ stat.catalog_clicks }}</td>
</tr>
{% endfor %}
{% endwith %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}

@ -0,0 +1,32 @@
{% extends 'base.html' %}
{% load static %}
{% block scripts %}
{% endblock %}
{% block body %}
<form method="post" class="form-horizontal" name="form2" id="form2" enctype="multipart/form-data"> {% csrf_token %}
<fieldset>
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-pencil"></i>{{ exposition }}</h2>
</div>
<div class="box-content">
{% for field in form %}
<div class="control-group {% if field.errors %}error{% endif %}">
<label class="control-label">{% if field.field.required %}<b>{{ field.label }}:</b>{% else %}{{ field.label }}{% endif %}</label>
<div class="controls">{{ field }}
<span class="help-inline">{{ field.errors }}</span>
</div>
</div>
{% endfor %}
</div>
</div>
</fieldset>
<div class="controls">
<input class="btn btn-large btn-primary" type="submit" value="Готово">
<input class="btn btn-large" type="reset" value="Отмена">
</div>
</form>
{% endblock %}

@ -0,0 +1,84 @@
{% extends 'base.html' %}
{% load static %}
{% block scripts %}
{# selects #}
<link href="{% static 'js/select/select2.css' %}" rel="stylesheet"/>
<script src="{% static 'js/select/select2.js' %}"></script>
<script>
$(function(){
$('#id_fr').datetimepicker({
todayHighlight: true,
format : 'yyyy-mm-dd',
minView:2
});
$('#id_to').datetimepicker({
todayHighlight: true,
format : 'yyyy-mm-dd',
minView:2
});
$('#id_theme').select2({width: "element"});
$('#id_country').select2({width: "element"});
$('#id_exposition').select2({
placeholder: 'Найти',
width: 'element',
ajax: {
url: '/admin/exposition/search/',
dataType: "json",
quietMillis: 200,
multiple: true,
data: function(term, page, theme){
return {term: term,
page: page};
},
results: function (data) {
var results = [];
$.each(data, function(index, item){
results.push({
id: item.id,
text: item.label
});
});
return {results: results};
}
},
initSelection : function(element, callback) {
var id= $(element).val();
var text = $(element).attr('data-init-text');
callback({id: id, text:text});
}
});
});
</script>
{% endblock %}
{% block body %}
<form method="post" class="form-horizontal" name="form2" id="form2" enctype="multipart/form-data"> {% csrf_token %}
<fieldset>
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-pencil"></i>{{ form.verbose }}</h2>
</div>
<div class="box-content">
{% for field in form %}
<div class="control-group {% if field.errors %}error{% endif %}">
<label class="control-label">{% if field.field.required %}<b>{{ field.label }}:</b>{% else %}{{ field.label }}{% endif %}</label>
<div class="controls">{{ field }}
<span class="help-inline">{{ field.errors }}</span>
</div>
</div>
{% endfor %}
</div>
</div>
</fieldset>
<div class="controls">
<input class="btn btn-large btn-primary" type="submit" value="Готово">
<input class="btn btn-large" type="reset" value="Отмена">
</div>
</form>
{% endblock %}

@ -0,0 +1,36 @@
{% extends 'base.html' %}
{% block body %}
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-arrow-down"></i>Список выставок в топе</h2>
</div>
<div class="box-content">
{% block list_table %}
<a class="btn btn-success" href="{% url 'expobanner-create_top' %}"><i class="icon-plus-sign icon-white"></i> Добавить выставку</a>
<table class="table table-hover">
<thead>
<tr>
<th>Выставка</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for item in object_list %}
<tr>
<td>{{ item }}</td>
<td><a href="{% url 'expobanner-update_top' item.top_id %}">Изменить</a> </td>
<td><a href="{% url 'expobanner_stat_top' item.top_id %}">Статистика</a> </td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
</div>
{# pagination #}
{% include 'admin/includes/admin_pagination.html' with page_obj=object_list %}
</div>
{% endblock %}

@ -62,26 +62,6 @@
{% endfor %}
{% endif %}
{% if import_errors %}
<div id="import_errors">
<table class="table table-hover">
<thead>
<tr>
<th>Событие</th>
<th>Ошибка</th>
</tr>
</thead>
<tbody>
{% for error in import_errors %}
<tr>
<td>{{ error.0 }}</td>
<td>{{ error.1 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<script>
$(document).ready(function(){
setTimeout(function(){
@ -90,5 +70,4 @@
});
</script>
{% endblock %}

@ -105,6 +105,15 @@
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class=" icon-circle-arrow-up"></i> Реклама<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/admin/expobanners/banners/control/">Управление банерами</a></li>
<li><a href="/admin/expobanners/paid/list/">Платные выставки</a></li>
<li><a href="/admin/expobanners/top/list/">Выставки в топе</a></li>
</ul>
</li>
</ul>
</div>

@ -0,0 +1,63 @@
{% extends 'base.html' %}
{% load static %}
{# Displays article form #}
{% block scripts %}
<script src="{% static 'ckeditor/ckeditor/ckeditor.js' %}"></script>
{# selects #}
<link href="{% static 'js/select/select2.css' %}" rel="stylesheet"/>
<script src="{% static 'js/select/select2.js' %}"></script>
<script src="{% static 'custom_js/make_select.js' %}"></script>
{# ajax #}
<script src="{% static 'custom_js/file_post_ajax.js' %}"></script>
<script src="{% static 'custom_js/select_tag.js' %}"></script>
{% endblock %}
{% block body %}
{{ request.LANGUAGE_CODE }}
<form method="post" class="form-horizontal" > {% csrf_token %}
<fieldset>
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-pencil"></i> Основная информация</h2>
</div>
<div class="box-content">
{# url/slug #}
<div class="control-group {% if form.url.errors %}error{% endif %}">
<label class="control-label"><b>{{ form.url.label }}:</b></label>
<div class="controls">
{{ form.langs }}
{{ form.url }}
<span class="help-inline">{{ form.url.errors }}</span>
</div>
</div>
{# title #}
<div class="control-group {% if form.title.errors %}error{% endif %}">
<label class="control-label">{{ form.title.label }}:</label>
<div class="controls">
{{ form.title }}
<span class="help-inline">{{ form.title.errors }}</span>
</div>
</div>
{# body #}
<div class="control-group {% if form.body.errors %}error{% endif %}">
<label class="control-label">{{ form.body.label }}:</label>
<div class="controls">
{{ form.body }}
<span class="help-inline">{{ form.body.errors }}</span>
</div>
</div>
</div>
</div>
<div class="controls">
<input class="btn btn-large btn-primary" type="submit" {% if request.path == '/admin/meta/seo/new/' %} value="Добавить" {% else %} value='Изменить' {% endif %}/>
<input class="btn btn-large" type="reset" value="Отмена">
</div>
</fieldset>
</form>
{% endblock %}

@ -0,0 +1,54 @@
{% extends 'base.html' %}
{% block body %}
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-arrow-down"></i>Список seo-текстов</h2>
</div>
<div class="box-content">
<table class="table table-hover">
<thead>
<tr>
<th>Аддрес страници</th>
<th>Заголовок</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for item in object_list %}
<tr>
<td><a href = "{{ item.url }}/">{{ item.url }}</a></td>
<td>{{ item.title }}</td>
<td class="center sorting_1">
<a class="btn-small btn-info" href='{% url "seo_edit" item.id %}'>
Изменить
</a>
</td>
<td>
<a class="btn-small btn-danger delete" href='{% url "seo_delete" item.id %}'>
Удалить
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a class="btn btn-success" href='{% url "seo_new" %}'>
<i class="icon-plus-sign icon-white"></i> Добавить seo-текст </a>
</div>
<div class="pagination pagination-centered">
<ul>
{% if page_obj.has_previous %}
<li> <a href="?page={{ page_obj.previous_page_number }}"></a></li>
{% endif %}
{% if page_obj.has_next %}
<li><a href="?page={{ page_obj.next_page_number }}"></a></li>
{% endif %}
</ul>
</div>
</div>
{% endblock %}

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% block sidebar %}{% endblock %}
{% block body %}
<form action="" method="post">{% csrf_token %}
<div class="controls">
<p>Вы точно хотите удалить seo-текст "{{ object.title }}" для страницы <a href = "{{ object.url }}"></a> ?</p>
<input class="btn btn-large btn-danger delete" type="submit" value="Да" />
<a class="btn btn-large btn-primary" href = {% url 'seo_all' %}>Нет</a>
</div>
</form>
{% endblock %}

@ -0,0 +1,90 @@
{% extends 'base.html' %}
{% load static %}
{# Displays article form #}
{% block scripts %}
<script src="{% static 'ckeditor/ckeditor/ckeditor.js' %}"></script>
{# selects #}
<link href="{% static 'js/select/select2.css' %}" rel="stylesheet"/>
<script src="{% static 'js/select/select2.js' %}"></script>
<script src="{% static 'custom_js/make_select.js' %}"></script>
{# ajax #}
<script src="{% static 'custom_js/file_post_ajax.js' %}"></script>
<script src="{% static 'custom_js/select_tag.js' %}"></script>
{% endblock %}
{% block body %}
{# Uses multilang.html template for translated fields #}
<form method="post" class="form-horizontal" > {% csrf_token %}
<fieldset>
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-pencil"></i> Основная информация</h2>
</div>
<div class="box-content">
{# url/slug #}
{% if request.path == '/admin/page/new/' %}
<div class="control-group {% if form.url.errors %}error{% endif %}">
<label class="control-label"><b>{{ form.url.label }}:</b></label>
<div class="controls">
{{ form.langs }}
{{ form.url }}
<span class="help-inline">{{ form.url.errors }}</span>
</div>
</div>
{% endif %}
{# h1 #}
<div class="control-group {% if form.h1.errors %}error{% endif %} ">
<label class="control-label"><b>{{ form.h1.label }}:</b></label>
<div class="controls">
{{ form.h1 }}
<span class="help-inline">{{ form.h1.errors }}</span>
</div>
</div>
{# title #}
<div class="control-group {% if form.title.errors %}error{% endif %}">
<label class="control-label">{{ form.title.label }}:</label>
<div class="controls">
{{ form.title }}
<span class="help-inline">{{ form.title.errors }}</span>
</div>
</div>
{# description #}
<div class="control-group {% if form.descriptions.errors %}error{% endif %}">
<label class="control-label">{{ form.descriptions.label }}:</label>
<div class="controls">
{{ form.descriptions }}
<span class="help-inline">{{ form.descriptions.errors }}</span>
</div>
</div>
{# keywords #}
<div class="control-group {% if form.keywords.errors %}error{% endif %}">
<label class="control-label">{{ form.keywords.label }}:</label>
<div class="controls">
{{ form.keywords }}
<span class="help-inline">{{ form.keywords.errors }}</span>
</div>
</div>
{# body #}
<div class="control-group {% if form.body.errors %}error{% endif %}">
<label class="control-label">{{ form.body.label }}:</label>
<div class="controls">
{{ form.body }}
<span class="help-inline">{{ form.body.errors }}</span>
</div>
</div>
</div>
</div>
<div class="controls">
<input class="btn btn-large btn-primary" type="submit" {% if request.path == '/admin/page/new/' %} value="Добавить" {% else %} value='Изменить' {% endif %}/>
<input class="btn btn-large" type="reset" value="Отмена">
</div>
</fieldset>
</form>
{% endblock %}

@ -0,0 +1,58 @@
{% extends 'base.html' %}
{% block body %}
<div class="box span8">
<div class="box-header well">
<h2><i class="icon-arrow-down"></i>Список страниц</h2>
</div>
<div class="box-content">
<table class="table table-hover">
<thead>
<tr>
<th>Название</th>
<th>Заголовок</th>
<th>Адресс</th>
<th>Создана</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for item in object_list %}
<tr>
<td>{{ item.title }}</td>
<td>{{ item.h1 }}</td>
<td><a href = "/admin/page/{{ item.url }}/">{{ item.url }}</a></td>
<td> {{ item.created|date:"Y-m-d H:i" }}</td>
<td class="center sorting_1">
<a class="btn-small btn-info" href="/admin/page/edit/{{ item.url }}">
Изменить
</a>
</td>
<td>
<a class="btn-small btn-danger delete" href="/admin/page/delete/{{ item.url }}/">
Удалить
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a class="btn btn-success" href="/admin/page/new/">
<i class="icon-plus-sign icon-white"></i> Добавить страницу </a>
</div>
<div class="pagination pagination-centered">
<ul>
{% if page_obj.has_previous %}
<li> <a href="?page={{ page_obj.previous_page_number }}"></a></li>
{% endif %}
{% if page_obj.has_next %}
<li><a href="?page={{ page_obj.next_page_number }}"></a></li>
{% endif %}
</ul>
</div>
</div>
{% endblock %}

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% block sidebar %}{% endblock %}
{% block body %}
<form action="" method="post">{% csrf_token %}
<div class="controls">
<p>Вы точно хотите удалить страницу "{{ object }}"?</p>
<input class="btn btn-large btn-danger delete" type="submit" value="Да" />
<a class="btn btn-large btn-primary" href = {% url 'page_list' %}>Нет</a>
</div>
</form>
{% endblock %}

@ -40,10 +40,13 @@
<td>{{ item.profile.country.name }}</td>
<td class="center sorting_1">
<a class="btn btn-info" href="/admin/translator/{{ item.id }}/">
<a class="btn btn-info" href="/admin/translator/change/{{ item.id }}">
<i class="icon-edit icon-white"></i> Изменить
</a>
<a class="btn btn-danger delete" href="/admin/translator/delete/{{ item.id }}/">
<i class="icon-trash icon-white"></i> Удалить
</a>
</td>
</tr>

@ -0,0 +1,7 @@
{% extends 'client/blank.html' %}
{% block main_part %}
<form method="post" action="{% url "require_email" %}">{% csrf_token %}
{{ form }}
<input type="submit" value="Send">
</form>
{% endblock %}

@ -17,6 +17,7 @@
<hr />
{% include 'client/includes/online_consult.html' %}
{% include 'client/includes/banners/aside_1.html' %}
{% block aside_banner1 %}
{% if theme_for_filter.id == 27 or theme_for_filter.id == 9 or theme_for_filter.id == 48 %}
@ -52,17 +53,19 @@
{% endblock %}
{% include 'client/includes/side_confs.html' %}
<hr />
{% include 'client/includes/banner_blocks/aside2.html' %}
{% include 'client/includes/banners/aside_2.html' %}
<hr />
<div class="s-news-list">
{% include 'client/includes/news.html' with news=news_list %}
</div>
{% include 'client/includes/banners/aside_3.html' %}
{% block aside_vk %}
<div class="vk-widget">
{% include 'client/includes/social_widjet.html' %}
</div>
{% endblock %}
{% include 'client/includes/banners/aside_4.html' %}
</aside>
<div class="mcl">
@ -70,7 +73,7 @@
{% include 'client/includes/catalog_search.html' %}
{% endwith %}
{% block under_search_baner %}
{% include 'client/includes/banners/under_search.html' %}
{% include 'client/includes/banners/search_under.html' %}
{% endblock %}
{% block bread_scrumbs %}
@ -100,12 +103,10 @@
{% endblock %}
</div>
{% block content_text %}
{% comment %}
{% with filter=filter %}
{% include 'includes/event_list_description.html' %}
{% endwith %}
{% endcomment %}
{% block seo_text_ %}
{% if seo_text %}
{% include 'client/includes/seo_text.html' with object=seo_text %}
{% endif %}
{% endblock %}
{% endblock %}

@ -0,0 +1,113 @@
{% extends 'blank.html' %}
{% load static %}
{% load i18n %}
{% load template_filters %}
{% block main_part %}
<section class="layout main-part">
<div class="layout-wrap">
<aside>
<div class="sbg"></div>
{% include 'menu.html' %}
<hr/>
{% include 'client/includes/feedback.html' %}
<hr />
{% include 'client/includes/online_consult.html' %}
{% block aside_banner1 %}
{% if theme_for_filter.id == 27 or theme_for_filter.id == 9 or theme_for_filter.id == 48 %}
<div class="sbnr">
<div class="sbnr-wrap">
<a href="/redirect/redirect/11/" target="_blank">
<img src="{% static 'client/img/partners/ipsa_.gif' %}" alt="" />
</a>
</div>
</div>
{% endif %}
{% endblock %}
{% include 'client/includes/services.html' %}
<hr />
{% include 'client/includes/announces.html' %}
{% block asside_banner2 %}
<!-- task EXPO-145-->
{% comment %}
<div class="sbnr">
<div class="sbnr-wrap">
<a href="/redirect/redirect/11/">
<img src="{% static 'client/img/partners/imgo.jpg' %}" alt="" />
</a>
</div>
</div>
{% endcomment %}
{% endblock %}
{% include 'client/includes/side_confs.html' %}
<hr />
<div class="s-news-list">
{% include 'client/includes/news.html' with news=news_list %}
</div>
{% block aside_vk %}
<div class="vk-widget">
{% include 'client/includes/social_widjet.html' %}
</div>
{% endblock %}
</aside>
<div class="mcl">
{% with search_form=search_form %}
{% include 'client/includes/catalog_search.html' %}
{% endwith %}
{% block under_search_baner %}
{% include 'client/includes/banners/under_search.html' %}
{% endblock %}
{% block bread_scrumbs %}
{% endblock %}
<div class="page-title">
{% block page_title %}
{% endblock %}
</div>
{% block page_filter %}
{% endblock %}
{% block page_body %}
<div class="page-body clearfix">
{% block content_list %}
{% endblock %}
{% block paginator %}
{% endblock %}
{% block content_footer_banner %}
{% endblock %}
</div>
{% block content_text %}
{% comment %}
{% with filter=filter %}
{% include 'includes/event_list_description.html' %}
{% endwith %}
{% endcomment %}
{% endblock %}
{% endblock %}
</div>
</div>
</section>
{% endblock %}

@ -77,41 +77,17 @@ This template include basic anf main styles and js files,
socialInputMask:['http://','https://']
});
</script>
<!-- Yandex.Metrika counter -->
<script type="text/javascript">
(function (d, w, c) {
(w[c] = w[c] || []).push(function() {
try {
w.yaCounter21606697 = new Ya.Metrika(
{id:21606697, webvisor:true, clickmap:true, trackLinks:true, accurateTrackBounce:true}
);
} catch(e) { }
});
var n = d.getElementsByTagName("script")[0],
s = d.createElement("script"),
f = function ()
{ n.parentNode.insertBefore(s, n); }
;
s.type = "text/javascript";
s.async = true;
s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//mc.yandex.ru/metrika/watch.js";
if (w.opera == "[object Opera]")
{ d.addEventListener("DOMContentLoaded", f, false); }
else
{ f(); }
})(document, window, "yandex_metrika_callbacks");
</script>
<noscript><div><img src="//mc.yandex.ru/watch/21606697" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function()
{ (i[r].q=i[r].q||[]).push(arguments)}
,i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-3151423-1', 'auto');
ga('send', 'pageview');
</script>
<!--test expo_b -->
<script>
window.sendData = {
"theme": [{% for item in themes %}{{ item }}{% endfor %}],
"country": "{{ country }}",
"city": "{{ city }}",
"tag": "{{ tag }}"
};
</script>
<script type="text/javascript" src="{% static 'client/js/banners.js' %}"></script>
</head>
<body {% block body_class %}{% endblock %}>
@ -232,14 +208,16 @@ This template include basic anf main styles and js files,
{% endif %}
{% endblock %}
{# if user doesnt have url- show form #}
{% if 'partial_pipeline' not in request.session %}
{% include 'client/popups/acquire_email.html' %}
{% endif %}
{% if not request.user.is_anonymous %}
{% if not request.user.url %}
{% include 'client/popups/user_information.html' with form=reg_complete %}
{% if request.GET.debug == '1' %}
<script src="{% static 'client/js/_modules/block.registration.completion.js' %}"></script>
{% else %}
<script src="{% static 'client/js_min/_modules/block.registration.completion.min.js' %}"></script>
<script type="text/javascript" src="{% static 'client/js_min/_modules/block.registration.completion.min.js' %}"></script>
{% endif %}
{% endif %}
{% endif %}

@ -0,0 +1,67 @@
{% extends 'base_catalog.html' %}
{% block page_title %}
<div class="page-title">
<h1>{{ object }}. Статистика</h1>
</div>
{% endblock %}
{% block content_list %}
<div class="m-article recovery-page">
{% if form %}
<form class="pw-form" method="post">{% csrf_token %}
<div>
<div class="input">
<p class="label">{{ form.stat_pswd.label }}</p>
</div>
{% if form.errors %}
{# если есть ошибка #}
<div class="required err input">
{{ form.stat_pswd }}
</div>
<div class="error-text">
{{ form.errors.stat_pswd.0 }}{# текст ошибки #}
</div>
{% else %}
{# ошибки нет #}
<div class="input">
{{ form.stat_pswd }}
</div>
{% endif %}
<div class="input">
<button type="submit" class="icon-check submit">Подтвердить</button>
</div>
</div>
</form>
{% else %}
<table width="100%">
<thead>
<tr>
<th>Дата</th>
<th>Показы</th>
<th>Клики</th>
<th>Уникальные показы</th>
<th>Уникальные клики</th>
</tr>
</thead>
<tbody>
{% with stats=object.banner_stat.all %}
{% for stat in stats %}
<tr>
<td>{{ stat.date|date:"Y-m-d" }}</td>
<td>{{ stat.view }}</td>
<td>{{ stat.click }}</td>
<td>{{ stat.unique_view }}</td>
<td>{{ stat.unique_click }}</td>
</tr>
{% endfor %}
{% endwith %}
</tbody>
</table>
{% endif %}
</div>
{% endblock %}

@ -0,0 +1,67 @@
{% extends 'base_catalog.html' %}
{% block page_title %}
<div class="page-title">
<h1>{{ object.get_event }}. Статистика</h1>
</div>
{% endblock %}
{% block content_list %}
<div class="m-article recovery-page">
{% if form %}
<form class="pw-form" method="post">{% csrf_token %}
<div>
<div class="input">
<p class="label">{{ form.stat_pswd.label }}</p>
</div>
{% if form.errors %}
{# если есть ошибка #}
<div class="required err input">
{{ form.stat_pswd }}
</div>
<div class="error-text">
{{ form.errors.stat_pswd.0 }}{# текст ошибки #}
</div>
{% else %}
{# ошибки нет #}
<div class="input">
{{ form.stat_pswd }}
</div>
{% endif %}
<div class="input">
<button type="submit" class="icon-check submit">Подтвердить</button>
</div>
</div>
</form>
{% else %}
<table width="100%">
<thead>
<tr>
<th>Дата</th>
<th>Официальный сайт</th>
<th>Билеты</th>
<th>Участие</th>
<th>Переходы с каталога</th>
</tr>
</thead>
<tbody>
{% with stats=object.paidstat_set.all %}
{% for stat in stats %}
<tr>
<td>{{ stat.date|date:"Y-m-d" }}</td>
<td>{{ stat.official_clicks }}</td>
<td>{{ stat.tickets_clicks }}</td>
<td>{{ stat.participation_clicks }}</td>
<td>{{ stat.catalog_clicks }}</td>
</tr>
{% endfor %}
{% endwith %}
</tbody>
</table>
{% endif %}
</div>
{% endblock %}

@ -17,10 +17,10 @@
{% endblock %}
{% block content_list %}
{% if not object.paid %}
{% include 'client/includes/exposition/exposition_object.html' with exposition=object %}
{% else %}
{% if object.paid_new_id and object.paid_new.public %}
{% include 'client/includes/exposition/expo_paid.html' with exposition=object %}
{% else %}
{% include 'client/includes/exposition/exposition_object.html' with exposition=object %}
{% endif %}
{% endblock %}

@ -1,219 +0,0 @@
{% extends 'base_catalog.html' %}
{% load static %}
{% load i18n %}
{% load template_filters %}
{% block content_list %}
{% block content_text %}
{% block page_body %}
<div class="m-article">
<div class="item-wrap event clearfix">
<aside>
{% if object_list.0.expohit %}
<div class="hit"></div>
{% endif %}
<div class="i-pict">
{% with obj=object_list.0 %}
{% include 'client/includes/show_logo.html' %}
{% endwith %}
</div>
<!--
<div class="i-rating" title="Рейтинг: 551">551</div>
-->
<div class="i-stats">
{% if object_list.0.visitors %}
<span class="visitors" title="Посетители">{{ object_list.0.visitors }}</span>
{% endif %}
{% if object_list.0.members %}
<span class="participants" title="Участники">{{ object_list.0.members }}</span>
{% endif %}
</div>
<div class="i-discount">
{% if object_list.0.discount %}
<a class="discount-button" href="#">{% trans 'Скидка' %} -{{ object_list.0.discount }}%</a>
<div class="dsc-text">{{ object_list.0.discount_description|safe }}</div>
{% endif %}
</div>
</aside>
<div class="i-info">
<header>
<div class="i-title">
{% if object_list.0.main_title %}
{{ object_list.0.main_title|safe }}
{% else %}
{{ object_list.0.name|safe }}
{% endif %}
</div>
</header>
<div class="i-date">
{% with obj=object_list.0 %}
{% include 'client/includes/show_date_block.html' %}
{% endwith %}
</div>
{% if object_list.0.place %}
<div class="i-address">
<header>
<div class="address">
{{ object_list.0.place.address.address }}
</div>
<div class="show-map"><a class="toggle-map" href="#">{% trans 'Раскрыть карту' %}</a></div>
</header>
<div class="i-map">
<div class="close-map"><a class="toggle-map" href="#">{% trans 'Скрыть карту' %}</a>
</div>
<div class="map-canvas" id="map-canvas"
data-coords="{{ object_list.0.place.address.lat }},{{ exposition.place.address.lng }}"></div>
</div>
</div>
{% endif %}
</div>
</div>
<div class="e-price">
<div class="sect-title">{% trans 'Стоимость посещения и участия' %}</div>
<div class="ep-wrap">
<div class="e-price-wrap">
<div class="epr-layout">
<div class="eprl-col">
<div class="epr-title"><span>{% trans 'Для посещения' %}</span></div>
<div class="epr-subtitle">{% trans 'Стоимость билетов' %}</div>
<div class="tp-wrap">
<ul class="pr-list">
{% if object_list.0.price_day %}
<li>
<div class="prl-value">{{ object_list.0.price_day }} €</div>
<div class="prl-descr"><span>{% trans 'на 1 день' %}</span></div>
</li>
{% endif %}
{% if object_list.0.price_all %}
<li>
<div class="prl-value">{{ object_list.0.price_all }} €</div>
<div class="prl-descr"><span>{% trans 'на все дни' %}</span></div>
</li>
{% endif %}
</ul>
<div class="tp-descr">{% trans 'Предварительная регистрация' %}</div>
</div>
<div class="tp-wrap">
<ul class="pr-list gray">
{% if object_list.0.price_day_bar %}
<li>
<div class="prl-value">{{ object_list.0.price_day_bar }} €</div>
<div class="prl-descr"><span>на 1 день</span></div>
</li>
{% endif %}
{% if object_list.0.price_all_bar %}
<li>
<div class="prl-value">{{ object_list.0.price_all_bar }} €</div>
<div class="prl-descr"><span>{% trans 'на все дни' %}</span></div>
</li>
{% endif %}
</ul>
<div class="tp-descr gray">{% trans 'Регистрация на' %}&nbsp;{% trans 'стойке' %}</div>
</div>
<div class="tp-btn-wrap">
<div class="tp-btn">
<a class="button big orange b-more" href="#">{% trans 'Заказать билет' %}</a>
</div>
<div class="tp-categories">
<div class="tpc-title">{% trans 'Выставка открыта для' %}:</div>
<ul>
{{ object_list.0.get_audience }}
</ul>
</div>
</div>
</div>
<div class="eprl-col">
<div class="epr-title"><span>{% trans 'Для участия' %}</span></div>
<div class="epr-subtitle">{% trans 'Стоимость аренды 1м²' %}</div>
<ul class="pr-list">
{% if object_list.0.max_closed_equipped_area %}
<li>
<div class="prl-value">{{ object_list.0.max_closed_equipped_area }} €</div>
<div class="prl-descr"><span>{% trans 'оборудованная площадь' %}</span></div>
</li>
{% endif %}
{% if object_list.0.max_closed_area %}
<li>
<div class="prl-value">{{ object_list.0.max_closed_area }} €</div>
<div class="prl-descr"><span>{% trans 'необорудованная площадь' %}</span></div>
</li>
{% endif %}
{% if object_list.0.max_open_area %}
<li>
<div class="prl-value">{{ object_list.0.max_open_area }} €</div>
<div class="prl-descr"><span>{% trans 'открытая площадь' %}</span></div>
</li>
{% endif %}
</ul>
<a class="button big orange b-more" href="#">{% trans 'Заявка на участие' %}</a>
<div class="epr-conditons">
{% if object_list.0.min_stand_size %}
<p>{% trans 'Минимальный размер стенда' %} — {{ object_list.0.min_stand_size }}м²</p>
{% endif %}
{% if object_list.0.registration_payment %}
<p>{% trans 'Регистрационный взнос' %} — {{ object_list.0.registration_payment }}€</p>
{% endif %}
{% if object_list.0.application_deadline %}
<p>{% trans 'Крайний срок подачи заявки' %} — {{ object_list.0.application_deadline }}</p>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="ed-back">
<a href="/{{ filter|generate_url:'event' }}">{{ object_list.0.name|safe }}</a>
</div>
<div class="i-sub-articles">
<ul>
{% for service in object_list.0.get_services %}
<li><a href="#">{{ service.name }}</a></li>
{% endfor %}
</ul>
</div>
{% endblock %}
{% endblock %}
{% endblock %}

@ -0,0 +1,4 @@
<div class="sbnr">
<div class="sbnr-wrap" id="expo_b_aside_1">
</div>
</div>

@ -0,0 +1,4 @@
<div class="sbnr">
<div class="sbnr-wrap" id="expo_b_aside_2">
</div>
</div>

@ -0,0 +1,4 @@
<div class="sbnr">
<div class="sbnr-wrap" id="expo_b_aside_3">
</div>
</div>

@ -0,0 +1,4 @@
<div class="sbnr">
<div class="sbnr-wrap" id="expo_b_aside_4">
</div>
</div>

@ -0,0 +1,3 @@
<div id="expo_b_catalog_inner">
</div>

@ -0,0 +1,3 @@
<div id="expo_b_detail_inner">
</div>

@ -0,0 +1,3 @@
<div class="abn" id="expo_b_header">
</div>

@ -0,0 +1,3 @@
<div class="abn" id="expo_b_under_search">
</div>

@ -0,0 +1,13 @@
<div id="expo_top_events">
</div>
<script>
/* НУЖНО ЛИ??? */
window.sendData = {
"theme": [{% for item in themes %}{{ item }}{% endfor %}],
"country": "{{ country }}",
"city": "{{ city }}",
"tag": "{{ tag }}"
};
var url = "/expo-b/get-tops/";
</script>

@ -29,11 +29,11 @@
<div class="dsc-text">{{ exposition.discount_description|safe|linebreaks }}</div>
{% endif %}
</div>
{% if exposition.paid.org_logo %}
{% if exposition.paid_new.logo %}
<div class="paid-partner-block">
<p class="partner-title">{% trans 'Организатор' %}</p>
<div class="i-pict">
<img src="{{ exposition.paid.org_logo.url }}" class="pic" alt="">
<img src="{{ exposition.paid_new.logo.url }}" class="pic" alt="">
</div>
</div>
{% endif %}
@ -115,7 +115,7 @@
</div>
<div class="i-sub-articles">
<a target="_blank" href="{{ exposition.paid.oficial_link.get_object_url }}" class="paid-partner-link">{% trans 'Официальный сайт выставки' %}</a>
<a target="_blank" href="{{ exposition.paid_new.official.get_click_link }}" class="paid-partner-link">{% trans 'Официальный сайт выставки' %}</a>
</div>
@ -125,7 +125,7 @@
<li class="s1">
<div class="label">{% trans 'Зарегистрируйтесь на событие' %}</div>
<a class="step"
href="{{ exposition.paid.tickets_link.get_object_url }}"
href="{{ exposition.paid_new.tickets.get_click_link }}"
target="_blank">
{% trans 'Билеты на выставку' %}
</a>
@ -133,7 +133,7 @@
<li class="s2">
<div class="label">{% trans 'Забронируйте площадь по лучшей цене' %}</div>
<a class="step" href="{{ exposition.paid.participation_link.get_object_url }}" target="_blank">Заявка на участие</a>
<a class="step" href="{{ exposition.paid_new.participation.get_click_link }}" target="_blank">Заявка на участие</a>
</li>
<li class="s3">

@ -0,0 +1,102 @@
{% load static %}
{% load i18n %}
{% load template_filters %}
<ul class="cat-list cl-exhibitions">
{% for obj in objects %}
<li class="cl-item {% if obj.canceled %}canceled{% endif %}">
<div class="cl-item-wrap clearfix">
{% if not obj.canceled %}
<a href="{% if not obj.paid_new_id %}{{ obj.get_permanent_url }}{% else %}{{ obj.get_paid_catalog_url }}{% endif %}">
{% if obj.expohit %}
<div class="hit"></div>
{% endif %}
<div class="cli-pict">
{% with obj=obj %}
{% include 'client/includes/show_logo.html' %}
{% endwith %}
</div>
</a>
{% else %}
<div class="cancel"></div>
<div class="cli-pict">
{% with obj=obj %}
{% include 'client/includes/show_logo.html' %}
{% endwith %}
</div>
{% endif %}
<div class="cli-info">
<div class="cli-top clearfix">
{% if obj.quality_label.ufi.is_set %}
<div class="cli-approved">
<img src="{% static 'client/img/approved-logo.png' %}" alt="" title="Approved Event" />
</div>
{% endif %}
<header>
<div class="cli-title"><a href="{% if not obj.paid_new_id %}{{ obj.get_permanent_url }}{% else %}{{ obj.get_paid_catalog_url }}{% endif %}">{{ obj.name|safe }}</a></div>
</header>
<div class="cli-descr">
{{ obj.main_title|safe }}
</div>
</div>
<div class="cli-bot clearfix">
<div class="cli-date">
{% with obj=obj %}
{% include 'client/includes/show_date_block.html' %}
{% endwith %}
</div>
{% if obj.country %}
<div class="cli-place">
<a href="{{ obj.catalog }}country/{{ obj.country.url }}/">{{ obj.country }}</a>, <a href="{{ obj.catalog }}city/{{ obj.city.url }}/">{{ obj.city }}</a>
{% if obj.place %}
, <a href="/places/{{ obj.place.url }}/">{{ obj.place }}</a>
{% endif %}
</div>
{% endif %}
</div>
</div>
<div class="cli-buttons clearfix">
<div class="cli-m-buttons">
{% include 'client/includes/exposition/services.html' with obj=obj %}
{% include 'client/includes/calendar_button.html' with obj=obj%}
<div class="{% if request.user.is_authenticated%}note-wrap{% else %}note-wrap-disabled{% endif %}">
{% with note=obj|note_by_user:request.user %}
<a class="button green icon-note {% if note %}active{% endif %} note-button" href="/expo/add-note/{{ obj.url }}/">{% trans 'заметка' %}</a>
<div class="note-overlay">
<form action="">
<textarea name="note_text" class="note-text"> {{ note }}</textarea>
</form>
</div>
{% endwith %}
</div>
{% if request.user.is_admin %}
<div class="note-wrap">
<a class="button green " href="/admin/exposition/{{ obj.url }}/">{% trans 'изменить' %}</a>
</div>
{% endif %}
<div></div>
</div>
<div class="cli-s-buttons">
{% include 'client/buttons/booking_button.html' with object=obj %}
</div>
</div>
</div>
<footer class="clearfix">
<div class="cli-stats">
{% if obj.visitors %}
<span class="visitors" title="Посетители">{{ obj.visitors }}</span>
{% endif %}
{% if obj.members %}
<span class="participants" title="Участники">{{ obj.members }}</span>
{% endif %}
</div>
<div class="cli-tags">
{% include 'client/includes/exposition/tags.html' with obj=obj %}
</div>
</footer>
</li>
{% endfor %}
</ul>

@ -3,13 +3,14 @@
{% load template_filters %}
{% with objects=object_list %}
{% if objects %}
<ul class="cat-list cl-exhibitions">
{% include 'client/includes/banners/tops.html' %}
<ul class="cat-list cl-exhibitions">
{% for obj in objects %}
<li class="cl-item {% if obj.canceled %}canceled{% endif %}">
<div class="cl-item-wrap clearfix">
{% if not obj.canceled %}
<a href="{{ obj.get_permanent_url }}">
<a href="{% if not obj.paid_new_id %}{{ obj.get_permanent_url }}{% else %}{{ obj.get_paid_catalog_url }}{% endif %}">
{% if obj.expohit %}
<div class="hit"></div>
{% endif %}
@ -36,7 +37,7 @@
</div>
{% endif %}
<header>
<div class="cli-title"><a href="{{ obj.get_permanent_url }}">{{ obj.name|safe }}</a></div>
<div class="cli-title"><a href="{% if not obj.paid_new_id %}{{ obj.get_permanent_url }}{% else %}{{ obj.get_paid_catalog_url }}{% endif %}">{{ obj.name|safe }}</a></div>
</header>
<div class="cli-descr">
{{ obj.main_title|safe }}
@ -104,30 +105,7 @@
{% endif %}
{% if forloop.counter == 8 %}
<!-- Яндекс.Директ -->
<script type="text/javascript">
yandex_partner_id = 58151;
yandex_site_bg_color = 'FFFFFF';
yandex_ad_format = 'direct';
yandex_font_size = 1;
yandex_direct_type = 'horizontal';
yandex_direct_border_type = 'block';
yandex_direct_limit = 3;
yandex_direct_title_font_size = 3;
yandex_direct_border_radius = true;
yandex_direct_links_underline = false;
yandex_direct_header_bg_color = 'FEEAC7';
yandex_direct_bg_color = 'FFF9F0';
yandex_direct_border_color = 'FBE5C0';
yandex_direct_title_color = '666666';
yandex_direct_url_color = '000000';
yandex_direct_text_color = '000000';
yandex_direct_hover_color = 'FF3333';
yandex_direct_sitelinks_color = '666666';
yandex_direct_favicon = false;
yandex_no_sitelinks = false;
document.write('<scr'+'ipt type="text/javascript" src="//an.yandex.ru/system/context.js"></scr'+'ipt>');
</script>
{% include 'client/includes/banners/catalog_inner.html' %}
{%endif %}
{% endfor %}

@ -208,29 +208,7 @@
<div class="clearfix">
<hr />
<script type="text/javascript">
yandex_partner_id = 58151;
yandex_site_bg_color = 'FFFFFF';
yandex_ad_format = 'direct';
yandex_font_size = 1;
yandex_direct_type = 'horizontal';
yandex_direct_border_type = 'block';
yandex_direct_limit = 3;
yandex_direct_title_font_size = 3;
yandex_direct_border_radius = true;
yandex_direct_links_underline = false;
yandex_direct_header_bg_color = 'FEEAC7';
yandex_direct_bg_color = 'FFF9F0';
yandex_direct_border_color = 'FBE5C0';
yandex_direct_title_color = '666666';
yandex_direct_url_color = '000000';
yandex_direct_text_color = '000000';
yandex_direct_hover_color = 'FF3333';
yandex_direct_sitelinks_color = '666666';
yandex_direct_favicon = false;
yandex_no_sitelinks = false;
document.write('<scr'+'ipt type="text/javascript" src="//an.yandex.ru/system/context.js"></scr'+'ipt>');
</script>
{% include 'client/includes/banners/detail_inner.html' %}
</div>
<hr />

@ -151,14 +151,15 @@
<div class="tp-btn-wrap">
<div class="tp-btn">
{% if not exposition.paid %}
{% if exposition.country_id in sng_countries %}
{% else %}
<a class="button big orange b-more" href="{{ exposition.get_permanent_url }}service/tickets/">{% trans 'Заказать билет' %}</a>
{% endif %}
{% if exposition.paid_new_id and exposition.paid_new.public %}
<a class="button big orange" href="{{ exposition.paid_new.tickets.get_click_link }}">{% trans 'Заказать билет' %}</a>
{% else %}
{% if exposition.country_id in sng_countries %}
{% else %}
<a class="button big orange" href="{{ exposition.paid.tickets_link.get_object_url }}">{% trans 'Заказать билет' %}</a>
<a class="button big orange b-more" href="{{ exposition.get_permanent_url }}service/tickets/">{% trans 'Заказать билет' %}</a>
{% endif %}
{% endif %}
</div>
{% if exposition.get_audience %}
<div class="tp-categories">
@ -222,10 +223,10 @@
{% else %}
<p class="mb-2em">{% trans 'Цены на площадь доступны по запросу' %}</p>
{% endif %}
{% if not exposition.paid %}
<a class="button big orange" href="{{ exposition.get_permanent_url }}service/participation/">{% trans 'Заявка на участие' %}</a>
{% if exposition.paid_new_id and exposition.paid_new.public %}
<a class="button big orange" href="{{ exposition.paid_new.participation.get_click_link }}">{% trans 'Заявка на участие' %}</a>
{% else %}
<a class="button big orange" href="{{ exposition.paid.participation_link.get_object_url }}">{% trans 'Заявка на участие' %}</a>
<a class="button big orange" href="{{ exposition.get_permanent_url }}service/participation/">{% trans 'Заявка на участие' %}</a>
{% endif %}
{% if exposition.min_stand_size or exposition.registration_payment or exposition.application_deadline %}

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

Loading…
Cancel
Save