merged with master

remotes/origin/1203
Ivan Kovalkovskyi 11 years ago
commit e1c343b3c9
  1. 72
      conference/views.py
  2. 2
      core/views.py
  3. 88
      expobanner/admin.py
  4. 18
      expobanner/admin_urls.py
  5. 147
      expobanner/forms.py
  6. 1
      expobanner/management/__init__.py
  7. 1
      expobanner/management/commands/__init__.py
  8. 42
      expobanner/management/commands/banner_log_check_previous_day.py
  9. 67
      expobanner/management/commands/banner_log_update.py
  10. 19
      expobanner/managers.py
  11. 3
      expobanner/mixins.py
  12. 102
      expobanner/models.py
  13. 57
      expobanner/stat_views.py
  14. 10
      expobanner/urls.py
  15. 112
      expobanner/utils.py
  16. 132
      expobanner/views.py
  17. 3
      exposition/models.py
  18. 130
      exposition/views.py
  19. 3
      functions/model_mixin.py
  20. 3
      meta/models.py
  21. 6
      place_exposition/urls.py
  22. 33
      place_exposition/views.py
  23. 24
      proj/settings.py
  24. 4
      proj/urls.py
  25. 36
      templates/admin/expobanner/banner_list.html
  26. 43
      templates/admin/expobanner/banner_stat.html
  27. 71
      templates/admin/expobanner/paid_create.html
  28. 38
      templates/admin/expobanner/paid_list.html
  29. 43
      templates/admin/expobanner/paid_stat.html
  30. 32
      templates/admin/expobanner/paid_update.html
  31. 84
      templates/admin/expobanner/top_create.html
  32. 36
      templates/admin/expobanner/top_list.html
  33. 2
      templates/admin/includes/admin_nav.html
  34. 42
      templates/client/base_catalog.html
  35. 113
      templates/client/base_page.html
  36. 73
      templates/client/blank.html
  37. 6
      templates/client/conference/catalog.html
  38. 6
      templates/client/conference/conference_list.html
  39. 4
      templates/client/conference/members.html
  40. 4
      templates/client/conference/visitors.html
  41. 67
      templates/client/expobanners/banner_stat.html
  42. 67
      templates/client/expobanners/paid_stat.html
  43. 3
      templates/client/exposition/catalog.html
  44. 5
      templates/client/exposition/catalog_theme.html
  45. 30
      templates/client/exposition/exposition_detail.html
  46. 219
      templates/client/exposition/exposition_price.html
  47. 7
      templates/client/includes/article/blog_list.html
  48. 7
      templates/client/includes/article/news_list.html
  49. 4
      templates/client/includes/banners/aside_1.html
  50. 24
      templates/client/includes/banners/aside_2.html
  51. 4
      templates/client/includes/banners/aside_3.html
  52. 4
      templates/client/includes/banners/aside_4.html
  53. 26
      templates/client/includes/banners/catalog_inner.html
  54. 2
      templates/client/includes/banners/catalog_inner_2.html
  55. 25
      templates/client/includes/banners/detail_inner.html
  56. 10
      templates/client/includes/banners/expo_detail.html
  57. 6
      templates/client/includes/banners/expo_list_baner.html
  58. 12
      templates/client/includes/banners/header.html
  59. 2
      templates/client/includes/banners/main_page_inner.html
  60. 3
      templates/client/includes/banners/search_under.html
  61. 13
      templates/client/includes/banners/tops.html
  62. 19
      templates/client/includes/banners/under_search.html
  63. 7
      templates/client/includes/company/company_list.html
  64. 29
      templates/client/includes/conference/conference_list.html
  65. 6
      templates/client/includes/conference/conference_object.html
  66. 10
      templates/client/includes/exposition/expo_paid.html
  67. 96
      templates/client/includes/exposition/expo_top.html
  68. 38
      templates/client/includes/exposition/exposition_list.html
  69. 30
      templates/client/includes/exposition/exposition_object.html
  70. 7
      templates/client/includes/exposition/members.html
  71. 19
      templates/client/includes/exposition/price.html
  72. 7
      templates/client/includes/exposition/search_result.html
  73. 7
      templates/client/includes/exposition/visitors.html
  74. 15
      templates/client/includes/header.html
  75. 7
      templates/client/includes/place/place_list.html
  76. 4
      templates/client/includes/place/place_object.html
  77. 23
      templates/client/index.html
  78. 2
      templates/client/page/page_view.html
  79. 2
      templates/client/place/catalog.html
  80. 3
      templates/client/robots.txt
  81. 87
      templates/client/static_client/js/banners.js
  82. 2
      templates/registration/acquire_email.html
  83. 2
      templates/registration/social_registration_complete.html

@ -10,6 +10,8 @@ from django.views.generic import ListView, DetailView
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils import translation from django.utils import translation
from service.models import Service
from service.views import order_forms
from note.models import Note from note.models import Note
from models import Conference from models import Conference
from accounts.models import User from accounts.models import User
@ -17,7 +19,6 @@ from country.models import Country
from city.models import City from city.models import City
from theme.models import Theme, Tag from theme.models import Theme, Tag
from service.order_forms import AdvertiseForm from service.order_forms import AdvertiseForm
from functions.search_forms import ExpositionSearchForm
from meta.views import MetadataMixin from meta.views import MetadataMixin
from functions.cache_mixin import JitterCacheMixin, CacheMixin from functions.cache_mixin import JitterCacheMixin, CacheMixin
@ -97,7 +98,6 @@ class ConferenceCatalog(JitterCacheMixin, MetadataMixin, ListView):
model = Conference model = Conference
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/conference/catalog.html' template_name = 'client/conference/catalog.html'
search_form = ExpositionSearchForm
filter_object = None filter_object = None
year = None year = None
month = None month = None
@ -152,10 +152,8 @@ class ConferenceCatalog(JitterCacheMixin, MetadataMixin, ListView):
return qs.order_by('data_begin') return qs.order_by('data_begin')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ConferenceCatalog, self).get_context_data(**kwargs) context = super(ConferenceCatalog, self).get_context_data(**kwargs)
context['search_form'] = self.search_form
context['filter_object'] = self.filter_object context['filter_object'] = self.filter_object
context['year'] = self.year context['year'] = self.year
context['month'] = self.month context['month'] = self.month
@ -164,6 +162,7 @@ class ConferenceCatalog(JitterCacheMixin, MetadataMixin, ListView):
class ConferenceCountryCatalog(ConferenceCatalog): class ConferenceCountryCatalog(ConferenceCatalog):
catalog_url = '/conference/country/' catalog_url = '/conference/country/'
def get_filtered_qs(self): def get_filtered_qs(self):
#this method used in parent get_queryset #this method used in parent get_queryset
slug = self.kwargs.get('slug') slug = self.kwargs.get('slug')
@ -173,6 +172,12 @@ class ConferenceCountryCatalog(ConferenceCatalog):
qs = self.model.enable.upcoming().filter(country=country) qs = self.model.enable.upcoming().filter(country=country)
return qs return qs
def get_context_data(self, **kwargs):
context = super(ConferenceCountryCatalog, self).get_context_data(**kwargs)
context['country'] = str(self.kwargs['country'].id)
return context
class ConferenceCityCatalog(ConferenceCatalog): class ConferenceCityCatalog(ConferenceCatalog):
catalog_url = '/conference/city/' catalog_url = '/conference/city/'
def get_filtered_qs(self): def get_filtered_qs(self):
@ -184,6 +189,11 @@ class ConferenceCityCatalog(ConferenceCatalog):
self.filter_object = city self.filter_object = city
return qs return qs
def get_context_data(self, **kwargs):
context = super(ConferenceCityCatalog, self).get_context_data(**kwargs)
context['city'] = str(self.kwargs['city'].id)
return context
class ConferenceThemeCatalog(ConferenceCatalog): class ConferenceThemeCatalog(ConferenceCatalog):
template_name = 'conference/catalog_theme.html' template_name = 'conference/catalog_theme.html'
@ -219,6 +229,9 @@ class ConferenceThemeCatalog(ConferenceCatalog):
context['country'] = self.country context['country'] = self.country
if self.city: if self.city:
context['city'] = self.city context['city'] = self.city
context['theme_for_filter'] = self.kwargs['theme']
context['themes'] = [str(self.kwargs['theme'].id)]
return context return context
@ -233,16 +246,20 @@ class ConferenceTagCatalog(ConferenceCatalog):
self.filter_object = tag self.filter_object = tag
return qs return qs
def get_context_data(self, **kwargs):
context = super(ConferenceTagCatalog, 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
class ConferenceVisitors(MetadataMixin, ListView): class ConferenceVisitors(MetadataMixin, ListView):
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
model = Conference model = Conference
#template_name = 'event_visitors.html'
template_name = 'client/conference/visitors.html' template_name = 'client/conference/visitors.html'
obj = None obj = None
search_form = ExpositionSearchForm
def get_queryset(self): def get_queryset(self):
slug = self.kwargs.get('slug') slug = self.kwargs.get('slug')
@ -252,20 +269,19 @@ class ConferenceVisitors(MetadataMixin, ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ConferenceVisitors, self).get_context_data(**kwargs) context = super(ConferenceVisitors, self).get_context_data(**kwargs)
context['object'] = self.obj obj = self.obj
context['search_form'] = self.search_form context['object'] = obj
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context return context
class ConferenceMembers(MetadataMixin, ListView): class ConferenceMembers(MetadataMixin, ListView):
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
model = Conference model = Conference
#template_name = 'event_visitors.html'
template_name = 'client/conference/members.html' template_name = 'client/conference/members.html'
obj = None obj = None
search_form = ExpositionSearchForm
def get_queryset(self): def get_queryset(self):
slug = self.kwargs.get('slug') slug = self.kwargs.get('slug')
@ -275,12 +291,14 @@ class ConferenceMembers(MetadataMixin, ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ConferenceMembers, self).get_context_data(**kwargs) context = super(ConferenceMembers, self).get_context_data(**kwargs)
context['object'] = self.obj obj = self.obj
context['search_form'] = self.search_form context['object'] = obj
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context return context
from service.models import Service
from service.views import order_forms
class ConferenceThankView(MetadataMixin, DetailView): class ConferenceThankView(MetadataMixin, DetailView):
model = Conference model = Conference
@ -324,7 +342,11 @@ class ConferenceServiceView(FormMixin, DetailView):
raise Http404 raise Http404
context['form'] = self.get_form(self.form_class) context['form'] = self.get_form(self.form_class)
context['service'] = service context['service'] = service
context['object'] = self.get_object() obj = self.get_object()
context['object'] = obj
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context return context
def form_valid(self, form): def form_valid(self, form):
@ -347,14 +369,11 @@ class ConferenceServiceView(FormMixin, DetailView):
'city':user.profile.city.name if user.profile.city else '', 'city':user.profile.city.name if user.profile.city else '',
'phone': user.profile.phone if user.profile.phone else ''} 'phone': user.profile.phone if user.profile.phone else ''}
return initial return initial
else: else:
return self.initial.copy() return self.initial.copy()
class ConferenceDetail(JitterCacheMixin, DetailView): class ConferenceDetail(JitterCacheMixin, DetailView):
cache_range = settings.CACHE_RANGE cache_range = settings.CACHE_RANGE
model = Conference model = Conference
@ -370,19 +389,21 @@ class ConferenceDetail(JitterCacheMixin, DetailView):
except City.DoesNotExist: except City.DoesNotExist:
return super(ConferenceDetail, self).dispatch(request, *args, **kwargs) return super(ConferenceDetail, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ConferenceDetail, self).get_context_data(**kwargs) context = super(ConferenceDetail, self).get_context_data(**kwargs)
context['advertising_form'] = AdvertiseForm() context['advertising_form'] = AdvertiseForm()
obj = self.object
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context return context
class ConferenceList(MetadataMixin, JitterCacheMixin, ListView): class ConferenceList(MetadataMixin, JitterCacheMixin, ListView):
cache_range = settings.CACHE_RANGE cache_range = settings.CACHE_RANGE
model = Conference model = Conference
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/conference/conference_list.html' template_name = 'client/conference/conference_list.html'
search_form = ExpositionSearchForm
catalog_url = '/conference/' catalog_url = '/conference/'
year = None year = None
month = None month = None
@ -410,7 +431,6 @@ class ConferenceList(MetadataMixin, JitterCacheMixin, ListView):
context = super(ConferenceList, self).get_context_data(**kwargs) context = super(ConferenceList, self).get_context_data(**kwargs)
context['month'] = self.month context['month'] = self.month
context['catalog_url'] = self.catalog_url context['catalog_url'] = self.catalog_url
context['search_form'] = self.search_form
context['year'] = self.year context['year'] = self.year
context['month'] = self.month context['month'] = self.month
return context return context

@ -244,7 +244,7 @@ class DeletePage(DeleteView):
class PageDetailed(DetailView): class PageDetailed(DetailView):
model = Page model = Page
template_name = 'client/base_page.html' template_name = 'client/base_catalog.html'
slug_field = 'url' slug_field = 'url'
slug_url_kwarg = 'url' slug_url_kwarg = 'url'

@ -1,8 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.views.generic import TemplateView, CreateView, ListView, UpdateView from django.views.generic import TemplateView, CreateView, ListView, UpdateView, DetailView
from django.conf import settings from django.conf import settings
from expobanner.models import URL, BannerGroup, Banner from django.http import HttpResponseRedirect
from expobanner.forms import UrlCreateForm, BannerCreateGroupForm, BannerCreateForm, BannerGroupUpdateForm 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): class BannersControl(TemplateView):
@ -52,6 +56,12 @@ class BannerGroupList(AbstractList):
class BannerList(AbstractList): class BannerList(AbstractList):
model = Banner model = Banner
verbose = u'Список банеров' 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 # UPDATE VIEWS
class AbstractUpdate(UpdateView): class AbstractUpdate(UpdateView):
@ -72,3 +82,75 @@ class BannerGroupUpdate(AbstractUpdate):
class BannerUpdate(AbstractUpdate): class BannerUpdate(AbstractUpdate):
model = Banner model = Banner
form_class = BannerCreateForm 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/'

@ -3,19 +3,27 @@ from django.conf.urls import patterns, url
from expobanner.admin import * from expobanner.admin import *
urlpatterns = patterns('expobanner.admin', urlpatterns = patterns('expobanner.admin',
# banners
url(r'^banners/control/$', BannersControl.as_view(), name='expobanner-baneers_control'), 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/url/$', CreateUrl.as_view(), name='expobanner-create_url'),
url(r'^banners/group/$', CreateBannerGroup.as_view(), name='expobanner-create_group'), 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/banner/$', CreateBanner.as_view(), name='expobanner-create_banner'),
url(r'^banners/url/list/$', UrlList.as_view(), name='expobanner-list_url'), 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/group/list/$', BannerGroupList.as_view(), name='expobanner-list_group'),
url(r'^banners/banner/list/$', BannerList.as_view(), name='expobanner-list_banner'), 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/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/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+)/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'),
) )

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django import forms from django import forms
from expobanner.models import URL, BannerGroup, Banner from expobanner.models import URL, BannerGroup, Banner, Paid, Top
from exposition.models import Exposition
from country.models import Country from country.models import Country
from city.models import City from city.models import City
from theme.models import Theme, Tag from theme.models import Theme, Tag
@ -34,7 +35,147 @@ class BannerCreateForm(forms.ModelForm):
#city = forms.CharField(label=u'Город', widget=forms.HiddenInput(), required=False) #city = forms.CharField(label=u'Город', widget=forms.HiddenInput(), required=False)
#tag = forms.CharField(label=u'Тег', widget=forms.HiddenInput(), required=False) #tag = forms.CharField(label=u'Тег', widget=forms.HiddenInput(), required=False)
class Meta: class Meta:
model = Banner model = Banner
exclude = ['created_at', 'updated_at', 'often', 'paid'] 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 Theme.objects.none()
def clean_country(self):
country_ids = self.cleaned_data['country']
if country_ids:
return Country.objects.filter(id__in=country_ids)
return Country.objects.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()

@ -23,6 +23,15 @@ class BiasedManager(models.Manager):
shuffle(result) shuffle(result)
return 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): class BannerGroupCached(models.Manager):
def all(self): def all(self):
key = 'banner_group_all' key = 'banner_group_all'
@ -56,3 +65,13 @@ class URLCached(models.Manager):
result = list(self.filter(public=True)) result = list(self.filter(public=True))
cache.set(key, result, 150) cache.set(key, result, 150)
return result 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)

@ -1,11 +1,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import random
import hashlib import hashlib
from datetime import datetime, date from datetime import datetime, date
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.conf import settings from django.conf import settings
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from .managers import BiasedManager, BannerGroupCached, URLCached 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 theme.models import Theme
from country.models import Country from country.models import Country
@ -64,7 +67,7 @@ class BannerGroup (models.Model):
return '/admin/expobanners/banners/group/%d/edit/'%self.id return '/admin/expobanners/banners/group/%d/edit/'%self.id
class Banner(models.Model): class Banner(models.Model, StatMixin):
objects = BiasedManager() objects = BiasedManager()
title = models.CharField(verbose_name=u'Заголовок', max_length=255, blank=True) title = models.CharField(verbose_name=u'Заголовок', max_length=255, blank=True)
@ -92,13 +95,18 @@ class Banner(models.Model):
html = models.BooleanField(verbose_name=_('HTML?'), default=False) html = models.BooleanField(verbose_name=_('HTML?'), default=False)
flash = models.BooleanField(verbose_name=_('Flash?'), 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) paid = models.BooleanField(verbose_name=_('Is Paid event link?'), default=False)
public = models.BooleanField(verbose_name=u'Активный', default=True) public = models.BooleanField(verbose_name=u'Активный', default=True)
created_at = models.DateTimeField(verbose_name=_('Created At'), auto_now_add=True) created_at = models.DateTimeField(verbose_name=_('Created At'), auto_now_add=True)
updated_at = models.DateTimeField(verbose_name=_('Updated At'), auto_now=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): def get_admin_url(self):
return '/admin/expobanners/banners/banner/%d/edit/'%self.id return '/admin/expobanners/banners/banner/%d/edit/'%self.id
@ -110,10 +118,9 @@ class Banner(models.Model):
key = str(datetime.now()) key = str(datetime.now())
return hashlib.md5(key).hexdigest() return hashlib.md5(key).hexdigest()
def log(self, request, type, key): def log(self, request, type):
log = { log = {
'type': type, 'type': type,
'key': key,
'banner': self, 'banner': self,
'group': self.group, 'group': self.group,
'ip': request.META.get('REMOTE_ADDR'), 'ip': request.META.get('REMOTE_ADDR'),
@ -150,6 +157,9 @@ class Banner(models.Model):
return ('banner_click', (), {'banner_id': self.pk, 'key': self.key()}) return ('banner_click', (), {'banner_id': self.pk, 'key': self.key()})
return get_absolute_url(self) return get_absolute_url(self)
def get_click_link(self):
return '/expo-b/click/%d/'%self.id
class Meta: class Meta:
ordering = ['sort'] ordering = ['sort']
verbose_name = _('Banner') verbose_name = _('Banner')
@ -158,7 +168,7 @@ class Banner(models.Model):
class Log(models.Model): class Log(models.Model):
banner = models.ForeignKey(Banner, related_name='banner_logs') banner = models.ForeignKey(Banner, related_name='banner_logs')
group = models.ForeignKey(BannerGroup, related_name='group_logs', verbose_name=_('Group'), blank=True) 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) 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')) user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name='users', verbose_name=_('User'))
@ -181,7 +191,7 @@ class Log(models.Model):
class LogStat(models.Model): class LogStat(models.Model):
banner = models.ForeignKey(Banner, related_name='banner_stat', verbose_name=_('Banner'), blank=True) 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) 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) urls = models.ManyToManyField(URL, related_name='url_bloks', verbose_name=_('URLs'), null=True, blank=True)
date = models.DateField(verbose_name=_('Data')) date = models.DateField(verbose_name=_('Data'))
@ -195,17 +205,26 @@ class LogStat(models.Model):
# ------------------ # ------------------
class Paid(models.Model): class Paid(models.Model, StatMixin):
tickets = models.ForeignKey(Banner, related_name='paid_tickets') tickets = models.ForeignKey(Banner, related_name='paid_tickets')
participation = models.ForeignKey(Banner, related_name='paid_participation') participation = models.ForeignKey(Banner, related_name='paid_participation')
official = models.ForeignKey(Banner, related_name='paid_official') official = models.ForeignKey(Banner, related_name='paid_official')
logo = models.ImageField(upload_to='/')# !!!!! catalog = models.ForeignKey(Banner, related_name='paid_catalog')
organiser = models.CharField(max_length=100) logo = models.ImageField(upload_to='expo-b/paid', blank=True)
active = models.BooleanField(default=True) organiser = models.CharField(max_length=100, blank=True)
public = models.BooleanField(default=True, verbose_name=u'Активная')
stat_pswd = models.CharField(max_length=16) stat_pswd = models.CharField(max_length=16)
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
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): class PaidStat(models.Model):
paid = models.ForeignKey(Paid) paid = models.ForeignKey(Paid)
@ -214,22 +233,33 @@ class PaidStat(models.Model):
price_views = models.PositiveIntegerField(default=0) price_views = models.PositiveIntegerField(default=0)
catalog_views = models.PositiveIntegerField(default=0) catalog_views = models.PositiveIntegerField(default=0)
catalog_clicks = models.PositiveIntegerField(default=0) catalog_clicks = models.PositiveIntegerField(default=0)
tickets_clicks = models.PositiveIntegerField(default=0)
participation_clicks = models.PositiveIntegerField(default=0)
class Top(models.Model): official_clicks = models.PositiveIntegerField(default=0)
catalog = models.CharField(max_length=16)
position = models.PositiveIntegerField(blank=True, null=True)
theme = models.ManyToManyField('theme.Theme', blank=True, null=True) class Top(models.Model, StatMixin):
excluded_tags = models.ManyToManyField('theme.Tag', blank=True, null=True) catalog = models.CharField(max_length=16, verbose_name=u'Каталог для топа')
country = models.ManyToManyField('country.Country', blank=True, null=True) position = models.PositiveIntegerField(blank=True, default=2, null=True, verbose_name=u'Позиция')
excluded_cities = models.ManyToManyField('city.City', blank=True, null=True) theme = models.ManyToManyField('theme.Theme', blank=True, null=True, verbose_name=u'Тематики')
fr = models.DateField(default=date.today()) excluded_tags = models.ManyToManyField('theme.Tag', blank=True, null=True, verbose_name=u'Исключить теги')
to = models.DateField(blank=True, null=True) 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) stat_pswd = models.CharField(max_length=16)
objects = models.Manager()
cached = TopCached()
class Meta: class Meta:
ordering = ['position'] ordering = ['position']
def get_event(self):
try:
return self.exposition_set.all()[0]
except IndexError:
return None
class TopStat(models.Model): class TopStat(models.Model):
date = models.DateField() date = models.DateField()
@ -239,3 +269,31 @@ class TopStat(models.Model):
city = models.ForeignKey('city.City', blank=True, null=True) city = models.ForeignKey('city.City', blank=True, null=True)
views = models.PositiveIntegerField(default=0) views = models.PositiveIntegerField(default=0)
clicks = 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})

@ -1,11 +1,13 @@
from django.conf.urls import url from django.conf.urls import url
from expobanner.stat_views import *
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^click/(?P<banner_id>\d{1,4})/(?P<key>[-\w]+)/$', views.click, name='banner_click'), url(r'^click/(?P<banner_id>\d{1,4})/$', views.click, name='banner_click'),
url(r'^view/(?P<banner_id>\d+)/(?P<key>[-\w]+)/$', views.view, name='banner_view'), #url(r'^view/(?P<banner_id>\d+)/$', views.view, name='banner_view'),
# #
url(r'^get-banners/$', views.get_banners), 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,112 @@
# -*- 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):
thematic_banners = []
url_banners = []
for banner in banners_list:
# check by theme
banner_theme_ids = [str(theme.id) for theme in banner.theme.all()]
if banner_theme_ids:
if params.get('theme'):
theme = params['theme']
flag = False
for th in theme:
if th in banner_theme_ids:
flag = True
if flag:
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
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))
def get_top_events(tops, params):
catalog = params.get('catalog')
country = params.get('country', '')
theme = params.get('theme', [])
city = params.get('city', '')
tag = params.get('tag', '')
catalog_tops = [item for item in tops if item.catalog == catalog]
good_tops = []
for top in catalog_tops:
country_ids = [str(item.id) for item in top.country.all()]
theme_ids = [str(item.id) for item in top.theme.all()]
excluded_tags_ids = [str(item.id) for item in top.excluded_tags.all()]
excluded_cities_ids = [str(item.id) for item in top.excluded_cities.all()]
if not country_ids and not theme_ids:
# universal top
good_tops.append(top)
continue
# check country
if country in country_ids and city not in excluded_cities_ids :
good_tops.append(top)
continue
# check theme
if tag in excluded_tags_ids:
continue
flag = False
for th in theme:
if th in theme_ids:
flag = True
continue
if flag:
good_tops.append(top)
sorted_top = sorted(good_tops, key=lambda x: x.position)
events = []
for top in sorted_top:
event = top.get_event()
if event:
events.append(event)
return events

@ -1,97 +1,29 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json import json
import re import re
import random
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import redirect, get_object_or_404 from django.shortcuts import redirect, get_object_or_404
from .models import Banner, BannerGroup, URL from django.shortcuts import render_to_response
from django.template import RequestContext
from .models import Banner, BannerGroup, URL, Top
from expobanner.utils import get_by_sort, get_banner_by_params, get_client_ip, get_top_events
def click(request, banner_id, key): def click(request, banner_id):
banner = get_object_or_404(Banner, pk=banner_id) banner = get_object_or_404(Banner, pk=banner_id)
banner.log(request, 2, key) banner.log(request, 2)
return redirect(banner.url) return redirect(banner.url)
def view(request, banner_id, key): def view(request, banner_id):
banner = get_object_or_404(Banner, pk=banner_id) banner = get_object_or_404(Banner, pk=banner_id)
banner.log(request, 1, key) banner.log(request, 1)
return redirect(banner.img.url) return redirect(banner.img.url)
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
from django.db import connection
def get_banner_by_params(banners_list, urls, params):
print('START. NUMBER of queries = %d'%len(connection.queries))
good_banners = []
for banner in banners_list:
print('-------------------------')
print('number of queries = %d'%len(connection.queries))
print(banner)
# 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:
good_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:
good_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:
good_banners.append(banner)
continue
print('-------------------------')
good_banners = get_by_sort(good_banners)
print('END. NUMBER of queries = %d'%len(connection.queries))
if good_banners:
return random.choice(good_banners)
return []
def get_banners(request): def get_banners(request):
#url = request.GET.get('url', '/')
url = request.META.get('HTTP_REFERER', '/')
# get urls by current url # get urls by current url
url = request.GET.get('url', '/')
urls = URL.cached.all() urls = URL.cached.all()
good_urls = [] good_urls = []
for u in urls: for u in urls:
@ -102,7 +34,7 @@ def get_banners(request):
elif url == u.url: elif url == u.url:
good_urls.append(u) good_urls.append(u)
# fill parameters dict # fill parameters dict
params = {'theme': request.GET.get('theme'), params = {'theme': request.GET.getlist('theme', []),
'tag': request.GET.get('tag'), 'tag': request.GET.get('tag'),
'country': request.GET.get('country'), 'country': request.GET.get('country'),
'city': request.GET.get('city'), 'city': request.GET.get('city'),
@ -110,17 +42,43 @@ def get_banners(request):
group_banners = BannerGroup.cached.group_banners() group_banners = BannerGroup.cached.group_banners()
result = [] result = []
# get banners for all groups
for group, banners in group_banners.iteritems(): for group, banners in group_banners.iteritems():
banner = get_banner_by_params(banners, good_urls, params) banner = get_banner_by_params(banners, good_urls, params)
result.append({'id': group, if banner:
'url': banner.url, if banner.js or banner.html:
'is_html': banner.html, text = banner.text
'is_flash': banner.flash, img = ''
'is_img': True, alt = ''
'html': banner.text, is_img = False
'img': banner.img.url 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') return HttpResponse(json.dumps(result, indent=4), content_type='application/json')
def get_top(request):
params = {'theme': request.GET.getlist('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)
context = {'objects': events}
return render_to_response('client/includes/exposition/expo_top.html', context, context_instance=RequestContext(request))

@ -157,6 +157,9 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin):
max_open_area = models.PositiveIntegerField(verbose_name='Максимальная цена открытой площади', max_open_area = models.PositiveIntegerField(verbose_name='Максимальная цена открытой площади',
blank=True, null=True) blank=True, null=True)
registration_payment = models.PositiveIntegerField(verbose_name='Регистрационный взнос', blank=True, null=True) registration_payment = models.PositiveIntegerField(verbose_name='Регистрационный взнос', blank=True, null=True)
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) #set manager of this model(fisrt manager is default)
objects = ExpoManager() objects = ExpoManager()
enable = ClientManager() enable = ClientManager()

@ -2,14 +2,14 @@
import json import json
import datetime import datetime
from django.http import HttpResponseRedirect, HttpResponse, HttpResponsePermanentRedirect from django.http import HttpResponseRedirect, HttpResponse, HttpResponsePermanentRedirect
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.conf import settings from django.conf import settings
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.shortcuts import get_object_or_404, render_to_response from django.shortcuts import get_object_or_404
from django.http import Http404 from django.http import Http404
from django.utils import translation from django.views.generic.edit import FormMixin
from django.core.mail import EmailMessage
#models #models
from accounts.models import User from accounts.models import User
from models import Exposition from models import Exposition
@ -23,9 +23,7 @@ from service.order_forms import AdvertiseForm
from functions.search_forms import ExpositionSearchForm from functions.search_forms import ExpositionSearchForm
from functions.custom_views import ExpoSearchView from functions.custom_views import ExpoSearchView
from meta.views import MetadataMixin from meta.views import MetadataMixin
from functions.cache_mixin import JitterCacheMixin, CacheMixin from functions.cache_mixin import JitterCacheMixin
class ExpositionBy(JitterCacheMixin, MetadataMixin, ListView): class ExpositionBy(JitterCacheMixin, MetadataMixin, ListView):
@ -151,37 +149,82 @@ class ExpoDetail(JitterCacheMixin, MetadataMixin, DetailView):
model = Exposition model = Exposition
slug_field = 'url' slug_field = 'url'
template_name = 'client/exposition/exposition_detail.html' template_name = 'client/exposition/exposition_detail.html'
queryset = Exposition.objects.language().select_related('place', 'city', 'country', 'paid_new')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ExpoDetail, self).get_context_data(**kwargs) context = super(ExpoDetail, self).get_context_data(**kwargs)
context['advertising_form'] = AdvertiseForm() context['advertising_form'] = AdvertiseForm()
obj = self.object
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context return context
class ExpositionProgramme(MetadataMixin, DetailView): class ExpositionProgramme(MetadataMixin, DetailView):
model = Exposition model = Exposition
slug_field = 'url' slug_field = 'url'
template_name = 'client/exposition/programm.html' template_name = 'client/exposition/programm.html'
queryset = Exposition.objects.language().select_related('place', 'city', 'country', 'paid_new')
def get_context_data(self, **kwargs):
context = super(ExpositionProgramme, self).get_context_data(**kwargs)
obj = self.object
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context
class ExpositionPrice(MetadataMixin, DetailView): class ExpositionPrice(MetadataMixin, DetailView):
model = Exposition model = Exposition
slug_field = 'url' slug_field = 'url'
template_name = 'client/exposition/price.html' template_name = 'client/exposition/price.html'
queryset = Exposition.objects.language().select_related('place', 'city', 'country', 'paid_new')
def get_context_data(self, **kwargs):
context = super(ExpositionPrice, self).get_context_data(**kwargs)
obj = self.object
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context
class ExpositionStatistic(MetadataMixin, DetailView): class ExpositionStatistic(MetadataMixin, DetailView):
model = Exposition model = Exposition
slug_field = 'url' slug_field = 'url'
template_name = 'client/exposition/statistic.html' template_name = 'client/exposition/statistic.html'
queryset = Exposition.objects.language().select_related('place', 'city', 'country', 'paid_new')
def get_context_data(self, **kwargs):
context = super(ExpositionStatistic, self).get_context_data(**kwargs)
obj = self.object
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context
from django.views.generic.edit import FormMixin, ModelFormMixin
class ExpositionThankView(MetadataMixin, DetailView): class ExpositionThankView(MetadataMixin, DetailView):
model = Exposition model = Exposition
slug_field = 'url' slug_field = 'url'
template_name = 'client/service/thank_u_page.html' template_name = 'client/service/thank_u_page.html'
def get_context_data(self, **kwargs):
context = super(ExpositionThankView, self).get_context_data(**kwargs)
obj = self.object
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context
def visit_redirect(request, slug): def visit_redirect(request, slug):
obj = get_object_or_404(Exposition, url=slug) obj = get_object_or_404(Exposition, url=slug)
redirect = obj.get_permanent_url() + 'price/' redirect = obj.get_permanent_url() + 'price/'
@ -224,7 +267,12 @@ class ExpositionServiceView(MetadataMixin, FormMixin, DetailView):
raise Http404 raise Http404
context['form'] = self.get_form(self.form_class) context['form'] = self.get_form(self.form_class)
context['service'] = self.service context['service'] = self.service
context['object'] = self.get_object() obj = self.get_object()
context['object'] = obj
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context return context
def form_valid(self, form): def form_valid(self, form):
@ -246,8 +294,6 @@ class ExpositionServiceView(MetadataMixin, FormMixin, DetailView):
'city':user.profile.city.name if user.profile.city else '', 'city':user.profile.city.name if user.profile.city else '',
'phone': user.profile.phone if user.profile.phone else ''} 'phone': user.profile.phone if user.profile.phone else ''}
return initial return initial
else: else:
return self.initial.copy() return self.initial.copy()
@ -258,12 +304,12 @@ class ExpoList(MetadataMixin, JitterCacheMixin, ListView):
model = Exposition model = Exposition
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/exposition/exposition_list.html' template_name = 'client/exposition/exposition_list.html'
search_form = ExpositionSearchForm
catalog_url = '/expo/' catalog_url = '/expo/'
year = None year = None
month = None month = None
def get_queryset(self): def get_queryset(self):
MONTHES = settings.MONTHES
if self.request.user.is_staff: if self.request.user.is_staff:
qs = self.model.objects.upcoming() qs = self.model.objects.upcoming()
else: else:
@ -284,24 +330,21 @@ class ExpoList(MetadataMixin, JitterCacheMixin, ListView):
context = super(ExpoList, self).get_context_data(**kwargs) context = super(ExpoList, self).get_context_data(**kwargs)
context['month'] = self.month context['month'] = self.month
context['catalog_url'] = self.catalog_url context['catalog_url'] = self.catalog_url
context['search_form'] = self.search_form
context['year'] = self.year context['year'] = self.year
context['month'] = self.month context['month'] = self.month
return context return context
MONTHES = settings.MONTHES
class ExpoCatalog(MetadataMixin, ListView): class ExpoCatalog(MetadataMixin, ListView):
model = Exposition model = Exposition
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
template_name = 'client/exposition/catalog.html' template_name = 'client/exposition/catalog.html'
search_form = ExpositionSearchForm
filter_object = None filter_object = None
year = None year = None
month = None month = None
country = None country = None
city = None city = None
paid = None
def get_filtered_qs(self): def get_filtered_qs(self):
# diferent for views # diferent for views
@ -350,12 +393,8 @@ class ExpoCatalog(MetadataMixin, ListView):
return qs.order_by('data_begin') return qs.order_by('data_begin')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ExpoCatalog, self).get_context_data(**kwargs) context = super(ExpoCatalog, self).get_context_data(**kwargs)
if self.paid:
context['paid'] = self.paid
context['search_form'] = self.search_form
context['filter_object'] = self.filter_object context['filter_object'] = self.filter_object
context['year'] = self.year context['year'] = self.year
context['month'] = self.month context['month'] = self.month
@ -364,6 +403,7 @@ class ExpoCatalog(MetadataMixin, ListView):
context['tag_for_filter'] = self.kwargs['tag'] context['tag_for_filter'] = self.kwargs['tag']
return context return context
class ExpoCountryCatalog(ExpoCatalog): class ExpoCountryCatalog(ExpoCatalog):
catalog_url = '/expo/country/' catalog_url = '/expo/country/'
def get_filtered_qs(self): def get_filtered_qs(self):
@ -375,6 +415,12 @@ class ExpoCountryCatalog(ExpoCatalog):
qs = self.model.enable.upcoming().filter(country=country) qs = self.model.enable.upcoming().filter(country=country)
return qs 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): class ExpoCityCatalog(ExpoCatalog):
catalog_url = '/expo/city/' catalog_url = '/expo/city/'
def get_filtered_qs(self): def get_filtered_qs(self):
@ -385,6 +431,10 @@ class ExpoCityCatalog(ExpoCatalog):
qs = self.model.enable.upcoming().filter(city=city) qs = self.model.enable.upcoming().filter(city=city)
self.filter_object = city self.filter_object = city
return qs 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): class ExpoThemeCatalog(ExpoCatalog):
@ -400,11 +450,8 @@ class ExpoThemeCatalog(ExpoCatalog):
city_slug = self.kwargs.get('city_slug') city_slug = self.kwargs.get('city_slug')
theme = get_object_or_404(Theme, url=slug) theme = get_object_or_404(Theme, url=slug)
self.kwargs['theme'] = theme self.kwargs['theme'] = theme
qs = self.model.enable.upcoming().filter(theme=theme)
qs = self.model.enable.upcoming().filter(theme=theme).exclude(paid__isnull=False)
paid= list(self.model.enable.filter(theme=theme).filter(paid__isnull=False))
if paid:
self.paid = paid
if country_slug: if country_slug:
country = get_object_or_404(Country, url=country_slug) country = get_object_or_404(Country, url=country_slug)
self.country = country self.country = country
@ -427,21 +474,19 @@ class ExpoThemeCatalog(ExpoCatalog):
if self.city: if self.city:
context['city'] = self.city context['city'] = self.city
context['theme_for_filter'] = self.kwargs['theme'] context['theme_for_filter'] = self.kwargs['theme']
context['themes'] = [str(self.kwargs['theme'].id)]
return context return context
class ExpoTagCatalog(ExpoCatalog): class ExpoTagCatalog(ExpoCatalog):
catalog_url = '/expo/tag/' catalog_url = '/expo/tag/'
def get_filtered_qs(self): def get_filtered_qs(self):
#this method used in parent get_queryset #this method used in parent get_queryset
slug = self.kwargs.get('slug') slug = self.kwargs.get('slug')
tag = get_object_or_404(Tag, url=slug) tag = get_object_or_404(Tag, url=slug)
self.kwargs['tag'] = tag self.kwargs['tag'] = tag
qs = self.model.enable.upcoming().filter(tag=tag).exclude(paid__isnull=False) qs = self.model.enable.upcoming().filter(tag=tag)
paid= list(self.model.enable.filter(tag=tag).filter(paid__isnull=False))
if paid:
self.paid = paid
self.filter_object = tag self.filter_object = tag
return qs return qs
@ -449,18 +494,16 @@ class ExpoTagCatalog(ExpoCatalog):
context = super(ExpoTagCatalog, self).get_context_data(**kwargs) context = super(ExpoTagCatalog, self).get_context_data(**kwargs)
tag = self.kwargs['tag'] tag = self.kwargs['tag']
context['theme_for_filter'] = tag.theme context['theme_for_filter'] = tag.theme
context['themes'] = [str(tag.theme.id)]
context['tag'] = str(self.kwargs['tag'].id)
return context return context
class ExpoVisitors(MetadataMixin, ListView): class ExpoVisitors(MetadataMixin, ListView):
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
model = Exposition model = Exposition
#template_name = 'event_visitors.html'
template_name = 'client/exposition/visitors.html' template_name = 'client/exposition/visitors.html'
obj = None obj = None
search_form = ExpositionSearchForm
def get_queryset(self): def get_queryset(self):
slug = self.kwargs.get('slug') slug = self.kwargs.get('slug')
@ -471,20 +514,19 @@ class ExpoVisitors(MetadataMixin, ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ExpoVisitors, self).get_context_data(**kwargs) context = super(ExpoVisitors, self).get_context_data(**kwargs)
context['object'] = self.obj obj = self.obj
context['search_form'] = self.search_form context['object'] = obj
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context return context
class ExpoMembers(MetadataMixin, ListView): class ExpoMembers(MetadataMixin, ListView):
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
model = Exposition model = Exposition
#template_name = 'event_visitors.html'
template_name = 'client/exposition/members.html' template_name = 'client/exposition/members.html'
obj = None obj = None
search_form = ExpositionSearchForm
def get_queryset(self): def get_queryset(self):
slug = self.kwargs.get('slug') slug = self.kwargs.get('slug')
@ -495,8 +537,11 @@ class ExpoMembers(MetadataMixin, ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ExpoMembers, self).get_context_data(**kwargs) context = super(ExpoMembers, self).get_context_data(**kwargs)
context['object'] = self.obj obj = self.obj
context['search_form'] = self.search_form context['object'] = obj
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
context['themes'] = [str(item.id) for item in obj.theme.all()]
return context return context
@ -532,11 +577,9 @@ def add_note(request, slug):
return HttpResponse(json.dumps(args), content_type='application/json') return HttpResponse(json.dumps(args), content_type='application/json')
from django.core.mail import send_mail
from django.core.mail import EmailMessage
def send_to_organiser(request, slug): def send_to_organiser(request, slug):
exposition = get_object_or_404(Exposition, url=slug) exposition = get_object_or_404(Exposition, url=slug)
mail_send = exposition.paid.organiser mail_send = 'evm@expomap.ru'
name = request.POST.get('person_inf') name = request.POST.get('person_inf')
email = request.POST.get('person') email = request.POST.get('person')
phone = request.POST.get('phone', '') phone = request.POST.get('phone', '')
@ -549,4 +592,3 @@ def send_to_organiser(request, slug):
redirect_to = '%sservice/thanks/'%exposition.get_permanent_url() redirect_to = '%sservice/thanks/'%exposition.get_permanent_url()
return HttpResponse(json.dumps({'success':True, 'redirect_to': redirect_to}), content_type='application/json') return HttpResponse(json.dumps({'success':True, 'redirect_to': redirect_to}), content_type='application/json')

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

@ -129,7 +129,6 @@ class SeoTextManager(TranslationManager):
cache_time = 120 cache_time = 120
def cache_get(self, *args, **kwargs): def cache_get(self, *args, **kwargs):
# ПЕРЕРОБИТИ
url = kwargs.get('url') url = kwargs.get('url')
lang = kwargs.get('lang')[:2] or translation.get_language()[:2] lang = kwargs.get('lang')[:2] or translation.get_language()[:2]
key = 'seo_text_cache' key = 'seo_text_cache'
@ -137,7 +136,7 @@ class SeoTextManager(TranslationManager):
if result: if result:
return result.get("%s_%s" % (lang, url)) return result.get("%s_%s" % (lang, url))
qs = SeoText.objects.language('all') qs = list(SeoText.objects.language('all'))
value_dict = {obj.language_code+'_'+obj.url: obj for obj in qs} value_dict = {obj.language_code+'_'+obj.url: obj for obj in qs}
cache.set(key, value_dict, self.cache_time) cache.set(key, value_dict, self.cache_time)
return value_dict.get("%s_%s" % (lang, url)) return value_dict.get("%s_%s" % (lang, url))

@ -1,13 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url from django.conf.urls import patterns, include, url
from views import PlaceSearchView, PlaceDetail, PlaceList, PlaceCityCatalog, PlaceCountryCatalog, PlacePhoto from views import PlaceDetail, PlaceList, PlaceCityCatalog, PlaceCountryCatalog, PlacePhoto
urlpatterns = patterns('', urlpatterns = patterns('',
# correct
url(r'search/', PlaceSearchView.as_view()),
# correct
#url(r'country/$', PlaceCountryCatalog.as_view()), #url(r'country/$', PlaceCountryCatalog.as_view()),
url(r'country/(?P<slug>.*)/page/(?P<page>\d+)/$', PlaceCountryCatalog.as_view(), {'meta_id':49}), url(r'country/(?P<slug>.*)/page/(?P<page>\d+)/$', PlaceCountryCatalog.as_view(), {'meta_id':49}),
url(r'country/(?P<slug>.*)/$', PlaceCountryCatalog.as_view(), {'meta_id':49}), url(r'country/(?P<slug>.*)/$', PlaceCountryCatalog.as_view(), {'meta_id':49}),

@ -42,19 +42,11 @@ def place(request, url, photo=None):
return render_to_response('photoreport.html', args, context_instance=RequestContext(request)) return render_to_response('photoreport.html', args, context_instance=RequestContext(request))
return render_to_response('place.html', args, context_instance=RequestContext(request)) return render_to_response('place.html', args, context_instance=RequestContext(request))
from functions.custom_views import ExpoSearchView
from functions.search_forms import PlaceSearchForm
class PlaceSearchView(ExpoSearchView):
#paginate_by = 10
template_name = 'place/search.html'
search_form = PlaceSearchForm
model = PlaceExposition
class PlaceDetail(JitterCacheMixin, MetadataMixin, DetailView): class PlaceDetail(JitterCacheMixin, MetadataMixin, DetailView):
cache_range = settings.CACHE_RANGE cache_range = settings.CACHE_RANGE
model = PlaceExposition model = PlaceExposition
search_form = PlaceSearchForm
slug_field = 'url' slug_field = 'url'
template_name = 'client/place/place_detail.html' template_name = 'client/place/place_detail.html'
@ -96,7 +88,9 @@ class PlaceDetail(JitterCacheMixin, MetadataMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(PlaceDetail, self).get_context_data(**kwargs) context = super(PlaceDetail, self).get_context_data(**kwargs)
context['search_form'] = self.search_form obj = self.object
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
return context return context
class PlacePhoto(ListView): class PlacePhoto(ListView):
@ -118,7 +112,10 @@ class PlacePhoto(ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(PlacePhoto, self).get_context_data(**kwargs) context = super(PlacePhoto, self).get_context_data(**kwargs)
context['object'] = self.obj obj = self.obj
context['object'] = obj
context['city'] = str(obj.city_id)
context['country'] = str(obj.country_id)
return context return context
@ -126,7 +123,6 @@ class PlaceList(JitterCacheMixin, MetadataMixin, ListView):
model = PlaceExposition model = PlaceExposition
paginate_by = 10 paginate_by = 10
template_name = 'client/place/place_list.html' template_name = 'client/place/place_list.html'
search_form = PlaceSearchForm
def get_queryset(self): def get_queryset(self):
@ -135,11 +131,6 @@ class PlaceList(JitterCacheMixin, MetadataMixin, ListView):
conf_qs = PlaceConference.objects.language().all() conf_qs = PlaceConference.objects.language().all()
return list(qs)+list(conf_qs) return list(qs)+list(conf_qs)
def get_context_data(self, **kwargs):
context = super(PlaceList, self).get_context_data(**kwargs)
context['search_form'] = self.search_form
return context
class PlaceCatalog(JitterCacheMixin, MetadataMixin, ListView): class PlaceCatalog(JitterCacheMixin, MetadataMixin, ListView):
cache_range = settings.CACHE_RANGE cache_range = settings.CACHE_RANGE
@ -170,6 +161,11 @@ class PlaceCountryCatalog(PlaceCatalog):
return list(qs) + list(conf_qs) return list(qs) + list(conf_qs)
def get_context_data(self, **kwargs):
context = super(PlaceCountryCatalog, self).get_context_data(**kwargs)
context['country'] = str(self.kwargs['country'].id)
return context
class PlaceCityCatalog(PlaceCatalog): class PlaceCityCatalog(PlaceCatalog):
catalog_url = '/places/' catalog_url = '/places/'
@ -182,3 +178,8 @@ class PlaceCityCatalog(PlaceCatalog):
qs = self.model.objects.language().select_related('country', 'city').filter(city=city).order_by('-rating') qs = self.model.objects.language().select_related('country', 'city').filter(city=city).order_by('-rating')
conf_qs = PlaceConference.objects.language().select_related('country', 'city').filter(city=city) conf_qs = PlaceConference.objects.language().select_related('country', 'city').filter(city=city)
return list(qs) + list(conf_qs) return list(qs) + list(conf_qs)
def get_context_data(self, **kwargs):
context = super(PlaceCityCatalog, self).get_context_data(**kwargs)
context['city'] = str(self.kwargs['city'].id)
return context

@ -351,7 +351,6 @@ INSTALLED_APPS = (
'pytils', # ?? 'pytils', # ??
'pymorphy', # ?? 'pymorphy', # ??
'password_reset', # reset password 'password_reset', # reset password
'django_crontab', # crons
'social.apps.django_app.default', # social auth 'social.apps.django_app.default', # social auth
'core', 'core',
'wizard' 'wizard'
@ -402,14 +401,21 @@ LOGGING = {
} }
} }
CRONJOBS = [ # TODO automate crons
('0 */1 * * *', 'django.core.management.call_command', ['update_index conference --age=1']), """
('0 */1 * * *', 'django.core.management.call_command', ['update_index exposition --age=1']), # update search indexes
('0 */12 * * *', 'django.core.management.call_command', ['update_index place_exposition --age=12']), 0 * * * * /usr/bin/python /var/www/proj/manage.py update_index conference --remove --age=6
('0 */24 * * *', 'django.core.management.call_command', ['update_index company --age=24']), 0 * * * * /usr/bin/python /var/www/proj/manage.py update_index exposition --remove --age=6
('0 */24 * * *', 'django.core.management.call_command', ['update_index theme --age=24']), 0 1,13 * * * /usr/bin/python /var/www/proj/manage.py update_index place_exposition --remove --age=24
('0 */24 * * *', 'django.core.management.call_command', ['update_index tag --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 THUMBNAIL_DEBUG = DEBUG

@ -8,7 +8,7 @@ import debug_toolbar
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
class Robot(TemplateView): class Robot(TemplateView):
template_name = 'robots.txt' template_name = 'client/robots.txt'
content_type = 'text/plain' content_type = 'text/plain'
class YandexCheck(TemplateView): class YandexCheck(TemplateView):
@ -73,9 +73,7 @@ urlpatterns = patterns('',
url(r'^', include('password_reset.urls')), url(r'^', include('password_reset.urls')),
url(r'^i18n/', include('django.conf.urls.i18n')), url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^redirect/', include('banners.urls')), url(r'^redirect/', include('banners.urls')),
#url(r'^social/', include('social_auth.urls')),
url(r'^', include('settings.old_urls')), url(r'^', include('settings.old_urls')),
#url(r'^search/', include('haystack.urls')),
url(r'^', include('service.urls')), url(r'^', include('service.urls')),
) )

@ -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,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 %}

@ -109,6 +109,8 @@
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class=" icon-circle-arrow-up"></i> Реклама<b class="caret"></b></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class=" icon-circle-arrow-up"></i> Реклама<b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="/admin/expobanners/banners/control/">Управление банерами</a></li> <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> </ul>
</li> </li>

@ -18,49 +18,33 @@
{% include 'client/includes/online_consult.html' %} {% include 'client/includes/online_consult.html' %}
{% block aside_banner1 %} {% include 'client/includes/banners/aside_1.html' %}
{% 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' %} {% include 'client/includes/services.html' %}
<hr /> <hr />
{% include 'client/includes/announces.html' %} {% include 'client/includes/announces.html' %}
{% block asside_banner2 %} {% include 'client/includes/side_confs.html' %}
<!-- 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 %}
<hr />
{% include 'client/includes/banners/aside_2.html' %}
{% endblock %}
{% include 'client/includes/side_confs.html' %}
<hr /> <hr />
<div class="s-news-list"> <div class="s-news-list">
{% include 'client/includes/news.html' with news=news_list %} {% include 'client/includes/news.html' with news=news_list %}
</div> </div>
{% include 'client/includes/banners/aside_3.html' %}
{% block aside_vk %} {% block aside_vk %}
<div class="vk-widget"> <div class="vk-widget">
{% include 'client/includes/social_widjet.html' %} {% include 'client/includes/social_widjet.html' %}
</div> </div>
{% endblock %} {% endblock %}
{% include 'client/includes/banners/aside_4.html' %}
</aside> </aside>
<div class="mcl"> <div class="mcl">
@ -68,7 +52,7 @@
{% include 'client/includes/catalog_search.html' %} {% include 'client/includes/catalog_search.html' %}
{% endwith %} {% endwith %}
{% block under_search_baner %} {% block under_search_baner %}
{% include 'client/includes/banners/under_search.html' %} {% include 'client/includes/banners/search_under.html' %}
{% endblock %} {% endblock %}
{% block bread_scrumbs %} {% block bread_scrumbs %}

@ -1,113 +0,0 @@
{% 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,55 +77,17 @@ This template include basic anf main styles and js files,
socialInputMask:['http://','https://'] socialInputMask:['http://','https://']
}); });
</script> </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 --> <!--test expo_b -->
<script> <script>
$(function () { window.sendData = {
var sendData = { "theme": [{{ themes|join:", " }}],
"url": "{{ request.path }}", "country": "{{ country }}",
"theme": "{{ theme.id }}", "city": "{{ city }}",
"country": "{{ country.id }}", "tag": "{{ tag }}"
"city": "{{ city.id }}", };
"tag": "{{ tag.id }}"
}
console.log(sendData);
});
</script> </script>
<script type="text/javascript" src="{% static 'client/js/banners.js' %}"></script>
</head> </head>
<body {% block body_class %}{% endblock %}> <body {% block body_class %}{% endblock %}>
@ -178,14 +140,6 @@ This template include basic anf main styles and js files,
{% if not request.COOKIES.popover_test1 %} {% if not request.COOKIES.popover_test1 %}
{% if theme_for_filter %} {% if theme_for_filter %}
{% if theme_for_filter.id == 2 %}
{% if False|random_social %}
{% include 'client/popups/auto_modal.html' %}
{% else %}
{% include 'client/popups/auto_banner.html' %}
{% endif %}
{% endif %}
{% if theme_for_filter.id == 54 or theme_for_filter.id == 26 or theme_for_filter.id == 22 or theme_for_filter.id == 15 or theme_for_filter.id == 44 or theme_for_filter.id == 30 %} {% if theme_for_filter.id == 54 or theme_for_filter.id == 26 or theme_for_filter.id == 22 or theme_for_filter.id == 15 or theme_for_filter.id == 44 or theme_for_filter.id == 30 %}
{% with r=False|random3 %} {% with r=False|random3 %}
{% if r == 1 %} {% if r == 1 %}
@ -201,18 +155,11 @@ This template include basic anf main styles and js files,
{% endif %} {% endif %}
{% if theme_for_filter.id == 32 %} {% if theme_for_filter.id == 32 %}
{% with r=False|random5 %} {% with r=False|random3 %}
{% if r == 1 %} {% if r == 1 %}
{% include 'client/popups/auto_modal.html' %}
{% endif %}
{% if r == 2 %}
{% include 'client/popups/auto_banner.html' %}
{% endif %}
{% if r == 3 %}
{% include 'client/popups/cemat_modal.html' %} {% include 'client/popups/cemat_modal.html' %}
{% endif %} {% endif %}
{% if r == 4 %} {% if r == 2 %}
{% include 'client/popups/cemat_banner1.html' %} {% include 'client/popups/cemat_banner1.html' %}
{% endif %} {% endif %}
{% if r == 0 %} {% if r == 0 %}

@ -27,14 +27,14 @@
<h1>{% if meta %}{{ meta.h1 }}{% else %}{% trans 'Конференции' %}: <strong>{{ filter_object.name }}</strong>{% endif %}</h1> <h1>{% if meta %}{{ meta.h1 }}{% else %}{% trans 'Конференции' %}: <strong>{{ filter_object.name }}</strong>{% endif %}</h1>
</div> </div>
{% include 'includes/exposition/catalog_filter_period.html' %} {% include 'client/includes/exposition/catalog_filter_period.html' %}
{% endblock %} {% endblock %}
{% block content_list %} {% block content_list %}
{% include 'includes/conference/conference_list.html' with object_list=object_list %} {% include 'client/includes/conference/conference_list.html' with object_list=object_list %}
{% endblock %} {% endblock %}
{% block paginator %} {% block paginator %}
{% include 'includes/catalog_paginator.html' with page_obj=page_obj %} {% include 'client/includes/catalog_paginator.html' with page_obj=page_obj %}
{% endblock %} {% endblock %}

@ -26,17 +26,17 @@
<h1>{% if meta %}{{ meta.h1 }}{% else %}{% trans 'Конференции' %}{% endif %}</h1> <h1>{% if meta %}{{ meta.h1 }}{% else %}{% trans 'Конференции' %}{% endif %}</h1>
</div> </div>
{% include 'includes/exposition/catalog_filter_period.html' %} {% include 'client/includes/exposition/catalog_filter_period.html' %}
{% endblock %} {% endblock %}
{% block content_list %} {% block content_list %}
{% include 'includes/conference/conference_list.html' with object_list=object_list %} {% include 'client/includes/conference/conference_list.html' with object_list=object_list %}
{% endblock %} {% endblock %}
{% block paginator %} {% block paginator %}
{% include 'includes/catalog_paginator.html' with page_obj=page_obj %} {% include 'client/includes/catalog_paginator.html' with page_obj=page_obj %}
{% endblock %} {% endblock %}

@ -17,9 +17,9 @@
{% endblock %} {% endblock %}
{% block content_list %} {% block content_list %}
{% include 'includes/exposition/members.html' with object_list=object_list %} {% include 'client/includes/exposition/members.html' with object_list=object_list %}
{% endblock %} {% endblock %}
{% block paginator %} {% block paginator %}
{% include 'includes/catalog_paginator.html' with page_obj=page_obj %} {% include 'client/includes/catalog_paginator.html' with page_obj=page_obj %}
{% endblock %} {% endblock %}

@ -18,9 +18,9 @@
{% block content_list %} {% block content_list %}
{% include 'includes/exposition/visitors.html' with object_list=object_list %} {% include 'client/includes/exposition/visitors.html' with object_list=object_list %}
{% endblock %} {% endblock %}
{% block paginator %} {% block paginator %}
{% include 'includes/catalog_paginator.html' with page_obj=page_obj %} {% include 'client/includes/catalog_paginator.html' with page_obj=page_obj %}
{% endblock %} {% endblock %}

@ -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 %}

@ -33,9 +33,6 @@
{% endblock %} {% endblock %}
{% block content_list %} {% block content_list %}
{% if paid %}
{% include 'includes/exposition/expo_list_paid.html' with object_list=paid %}
{% endif %}
{% include 'includes/exposition/exposition_list.html' with object_list=object_list %} {% include 'includes/exposition/exposition_list.html' with object_list=object_list %}
{% endblock %} {% endblock %}

@ -49,18 +49,13 @@
{% block page_title %} {% block page_title %}
<div class="page-title"> <div class="page-title">
{# <h1>{% trans 'Выставки' %}: <strong>{{ filter_object.name }}</strong></h1> #}
<h1>{% if meta %}{{ meta.h1 }}{% else %}{% trans 'Выставки' %}: <strong>{{ filter_object.name }}</strong>{% endif %}</h1> <h1>{% if meta %}{{ meta.h1 }}{% else %}{% trans 'Выставки' %}: <strong>{{ filter_object.name }}</strong>{% endif %}</h1>
</div> </div>
{% include 'includes/exposition/catalog_filter_period.html' %} {% include 'includes/exposition/catalog_filter_period.html' %}
{% endblock %} {% endblock %}
{% block content_list %} {% block content_list %}
{% if paid %}
{% include 'includes/exposition/exposition_list.html' with object_list=paid %}
{% endif %}
{% include 'includes/exposition/exposition_list.html' with object_list=object_list %} {% include 'includes/exposition/exposition_list.html' with object_list=object_list %}
{% endblock %} {% endblock %}

@ -17,10 +17,10 @@
{% endblock %} {% endblock %}
{% block content_list %} {% block content_list %}
{% if not object.paid %} {% if object.paid_new_id and object.paid_new.public %}
{% include 'client/includes/exposition/exposition_object.html' with exposition=object %}
{% else %}
{% include 'client/includes/exposition/expo_paid.html' with exposition=object %} {% include 'client/includes/exposition/expo_paid.html' with exposition=object %}
{% else %}
{% include 'client/includes/exposition/exposition_object.html' with exposition=object %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
@ -34,21 +34,14 @@
{% with theme_ids=object.theme_ids %} {% with theme_ids=object.theme_ids %}
{% if 32 in theme_ids %} {% if 32 in theme_ids %}
{% with r=False|random5 %} {% with r=False|random3 %}
{% if r == 1 %} {% if r == 0 %}
{% include 'client/popups/auto_modal.html' %}
{% endif %}
{% if r == 2 %}
{% include 'client/popups/auto_banner.html' %}
{% endif %}
{% if r == 3 %}
{% include 'client/popups/cemat_modal.html' %} {% include 'client/popups/cemat_modal.html' %}
{% endif %} {% endif %}
{% if r == 4 %} {% if r == 1 %}
{% include 'client/popups/cemat_banner1.html' %} {% include 'client/popups/cemat_banner1.html' %}
{% endif %} {% endif %}
{% if r == 5 %} {% if r == 2 %}
{% include 'client/popups/cemat_banner2.html' %} {% include 'client/popups/cemat_banner2.html' %}
{% endif %} {% endif %}
{% endwith %} {% endwith %}
@ -65,14 +58,7 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endwith %} {% endwith %}
{% else %}
{% if 2 in theme_ids %}
{% if False|random_social %}
{% include 'client/popups/auto_modal.html' %}
{% else %}
{% include 'client/popups/auto_banner.html' %}
{% endif %}
{% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endwith %} {% endwith %}

@ -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 %}

@ -10,6 +10,13 @@
<strong><span>{{ blog.created|date:"d E Y" }}</span>{% if blog.tag.all.exists %}{% include 'includes/article_tags.html' with obj=blog %}{% endif %}</strong> <strong><span>{{ blog.created|date:"d E Y" }}</span>{% if blog.tag.all.exists %}{% include 'includes/article_tags.html' with obj=blog %}{% endif %}</strong>
</div> </div>
</div> </div>
{% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %}
{% if forloop.counter == 8 %}
{% include 'client/includes/banners/catalog_inner.html' %}
{%endif %}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>

@ -10,6 +10,13 @@
<strong><span>{{ news.publish_date|date:"d E Y" }}</span>{% with event=news.get_event %}{% if event %}<a href="{{ event.get_permanent_url }}" title=""><b>{{ event.name }}</b></a>{% endif %}{% endwith %}</strong> <strong><span>{{ news.publish_date|date:"d E Y" }}</span>{% with event=news.get_event %}{% if event %}<a href="{{ event.get_permanent_url }}" title=""><b>{{ event.name }}</b></a>{% endif %}{% endwith %}</strong>
</div> </div>
</div> </div>
{% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %}
{% if forloop.counter == 8 %}
{% include 'client/includes/banners/catalog_inner.html' %}
{%endif %}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>

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

@ -0,0 +1,24 @@
<div class="sbnr">
<div class="sbnr-wrap" id="expo_b_aside_2">
<!-- Яндекс.Директ -->
<script type="text/javascript">
yandex_partner_id = 58151;
yandex_site_bg_color = 'FFFFF';
yandex_ad_format = 'direct';
yandex_font_size = 1;
yandex_direct_type = 'vertical';
yandex_direct_limit = 3;
yandex_direct_title_font_size = 3;
yandex_direct_links_underline = false;
yandex_direct_title_color = '666666';
yandex_direct_url_color = '000000';
yandex_direct_text_color = '000000';
yandex_direct_hover_color = 'FF8000';
yandex_direct_sitelinks_color = 'FF8000';
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>
</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,26 @@
<div id="expo_b_catalog_inner">
<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>
</div>

@ -0,0 +1,2 @@
<div id="expo_b_catalog_inner_2">
</div>

@ -0,0 +1,25 @@
<div id="expo_b_detail_inner">
<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>
</div>

@ -1,12 +1,6 @@
{% load static %} {% load static %}
{% load template_filters %} {% load template_filters %}
<div class="abn"> <div class="abn" id="expo_b_detail_inner_2">
{% if object.theme.all.0.id in banner_themes %}
<a target="_blank" href="/redirect/redirect/24/"><img src="{% static 'client/img/partners/unnamed_2.gif' %}" alt="" /></a>
{% else %}
{% if object.theme.all.1.id in banner_themes %}
<a target="_blank" href="/redirect/redirect/24/"><img src="{% static 'client/img/partners/unnamed_2.gif' %}" alt="" /></a>
{% endif %}
{% endif %}
</div> </div>

@ -1,6 +0,0 @@
{% load static %}
<div class="abn">
{% if theme_for_filter.id in banner_themes or tag_for_filter.id in banner_tags %}
<a target="_blank" href="/redirect/redirect/24/"><img src="{% static 'client/img/partners/unnamed_2.gif' %}" alt="" /></a>
{% endif %}
</div>

@ -0,0 +1,12 @@
<div class="abn" id="expo_b_header">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- 468 на 60 -->
<ins class="adsbygoogle"
style="display:inline-block;width:468px;height:60px"
data-ad-client="ca-pub-5242360491829403"
data-ad-slot="4482648777"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</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": [{{ themes|join:", " }}],
"country": "{{ country }}",
"city": "{{ city }}",
"tag": "{{ tag }}"
};
var url = "/expo-b/get-tops/";
</script>

@ -1,19 +0,0 @@
{% load static %}
{% load template_filters %}
<div class="abn">
{% with r=False|random4 %}
{% ifequal r 0 %}
<a target="_blank" href="/redirect/redirect/57/"><img src="{% static 'client/img/partners/cemat15_900x130_bilet.gif' %}" alt="" /></a>
{% endifequal %}
{% ifequal r 1 %}
<a target="_blank" href="/redirect/redirect/58/"><img src="{% static 'client/img/partners/beach.png' %}" alt="" /></a>
{% endifequal %}
{% ifequal r 2 %}
<a target="_blank" href="/redirect/redirect/59/"><img src="{% static 'client/img/partners/mims15_900x130_bilet.gif' %}" alt="" /></a>
{% endifequal %}
{% ifequal r 3 %}
<a target="_blank" href="/redirect/redirect/61/"><img src="{% static 'client/img/partners/IPSA_2015_web_900x130.gif' %}" alt="" /></a>
{% endifequal %}
{% endwith %}
</div>

@ -60,5 +60,12 @@
</div> </div>
</footer> </footer>
</li> </li>
{% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %}
{% if forloop.counter == 8 %}
{% include 'client/includes/banners/catalog_inner.html' %}
{%endif %}
{% endfor %} {% endfor %}
</ul> </ul>

@ -92,31 +92,12 @@
</div> </div>
</footer> </footer>
</li> </li>
{% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %}
{% if forloop.counter == 8 %} {% if forloop.counter == 8 %}
<!-- Яндекс.Директ --> {% include 'client/includes/banners/catalog_inner.html' %}
<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>
{%endif %} {%endif %}
{% endfor %} {% endfor %}

@ -196,6 +196,12 @@
{% endif %} {% endif %}
</dl> </dl>
</div> </div>
<div class="clearfix">
<hr />
{% include 'client/includes/banners/detail_inner.html' %}
</div>
<hr /> <hr />
<div class="i-members clearfix"> <div class="i-members clearfix">
<div class="im-participants"> <div class="im-participants">

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

@ -1,27 +1,32 @@
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% load template_filters %} {% load template_filters %}
{% with objects=object_list %}
{% if objects %}
<ul class="cat-list cl-exhibitions"> <ul class="cat-list cl-exhibitions">
{% for obj in objects %} {% for obj in objects %}
<li class="cl-item {% if obj.canceled %}canceled{% endif %}"> <li class="cl-item {% if obj.canceled %}canceled{% endif %}">
<div class="cl-item-wrap clearfix"> <div class="cl-item-wrap clearfix">
<a href="{{ obj.get_permanent_url }}"> {% if not obj.canceled %}
{% if obj.canceled %} <a href="{% if not obj.paid_new_id %}{{ obj.get_permanent_url }}{% else %}{{ obj.get_paid_catalog_url }}{% endif %}">
<div class="cancel"></div> {% if obj.expohit %}
{% else %} <div class="hit"></div>
{% if obj.expohit %} {% endif %}
<div class="hit"></div> <div class="cli-pict">
{% endif %} {% with obj=obj %}
{% endif %} {% include 'client/includes/show_logo.html' %}
<div class="cli-pict"> {% endwith %}
{% with obj=obj %} </div>
{% include 'client/includes/show_logo.html' %} </a>
{% endwith %}
</div> {% else %}
</a> <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-info">
<div class="cli-top clearfix"> <div class="cli-top clearfix">
{% if obj.quality_label.ufi.is_set %} {% if obj.quality_label.ufi.is_set %}
@ -30,7 +35,7 @@
</div> </div>
{% endif %} {% endif %}
<header> <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> </header>
<div class="cli-descr"> <div class="cli-descr">
{{ obj.main_title|safe }} {{ obj.main_title|safe }}
@ -92,63 +97,6 @@
</div> </div>
</footer> </footer>
</li> </li>
{% 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>
{%endif %}
{% endfor %} {% endfor %}
</ul> </ul>
{% else %}
<p class="message-not-found">
<span class="message">
{% trans "Выставки по указанным параметрам не найдены. Попробуйте задать менее точный запрос по теме или расширить период времени" %}
</span>
</p>
{% endif %}
{% endwith %}
{% block scripts %}
{% if request.GET.debug == '1' %}
<script src="{% static 'client/js/_modules/block.exposition.list.js' %}"></script>
{% else %}
<script src="{% static 'client/js_min/_modules/block.exposition.list.min.js' %}"></script>
{% endif %}<script>
EXPO.exposition.list.init({
note:{
wrapClass:'note-wrap',
wrapDisabledClass:'note-wrap-disabled',
buttonClass:'note-button',
inputClass:'note-text'
},
addCalendarText:"{% trans 'В расписание' %}",
removeCalendarText:"{% trans 'Из расписания' %}"
});
</script>
{% endblock %}

@ -3,13 +3,14 @@
{% load template_filters %} {% load template_filters %}
{% with objects=object_list %} {% with objects=object_list %}
{% if objects %} {% if objects %}
<ul class="cat-list cl-exhibitions"> {% include 'client/includes/banners/tops.html' %}
<ul class="cat-list cl-exhibitions">
{% for obj in objects %} {% for obj in objects %}
<li class="cl-item {% if obj.canceled %}canceled{% endif %}"> <li class="cl-item {% if obj.canceled %}canceled{% endif %}">
<div class="cl-item-wrap clearfix"> <div class="cl-item-wrap clearfix">
{% if not obj.canceled %} {% 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 %} {% if obj.expohit %}
<div class="hit"></div> <div class="hit"></div>
{% endif %} {% endif %}
@ -36,7 +37,7 @@
</div> </div>
{% endif %} {% endif %}
<header> <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> </header>
<div class="cli-descr"> <div class="cli-descr">
{{ obj.main_title|safe }} {{ obj.main_title|safe }}
@ -99,35 +100,12 @@
</footer> </footer>
</li> </li>
{% if forloop.counter == 5 or objects|length < 5 %} {% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/expo_list_baner.html' %} {% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %} {% endif %}
{% if forloop.counter == 8 %} {% if forloop.counter == 8 %}
<!-- Яндекс.Директ --> {% include 'client/includes/banners/catalog_inner.html' %}
<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>
{%endif %} {%endif %}
{% endfor %} {% endfor %}

@ -206,32 +206,10 @@
</dl> </dl>
</div> </div>
<div class="clearfix"> <div class="clearfix">
<hr /> <hr />
<script type="text/javascript"> {% include 'client/includes/banners/detail_inner.html' %}
yandex_partner_id = 58151; </div>
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>
</div>
<hr /> <hr />
<div class="i-members clearfix"> <div class="i-members clearfix">

@ -49,5 +49,12 @@
</div> </div>
</footer> </footer>
</li> </li>
{% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %}
{% if forloop.counter == 8 %}
{% include 'client/includes/banners/catalog_inner.html' %}
{%endif %}
{% endfor %} {% endfor %}
</ul> </ul>

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

@ -83,6 +83,13 @@
</div> </div>
</footer> </footer>
</li> </li>
{% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %}
{% if forloop.counter == 8 %}
{% include 'client/includes/banners/catalog_inner.html' %}
{%endif %}
{% endfor %} {% endfor %}
</ul> </ul>
{% block scripts %} {% block scripts %}

@ -51,6 +51,13 @@
</div> </div>
</footer> </footer>
</li> </li>
{% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %}
{% if forloop.counter == 8 %}
{% include 'client/includes/banners/catalog_inner.html' %}
{%endif %}
{% endfor %} {% endfor %}
</ul> </ul>

@ -37,7 +37,6 @@
{% endfor %} {% endfor %}
{% if user.is_staff %} {% if user.is_staff %}
<li><a href="/admin/">admin</a></li> <li><a href="/admin/">admin</a></li>
<li><a target="_blank" href="/expo-b/get-banners/?country=Russia">TEST</a></li>
{% endif %} {% endif %}
</ul> </ul>
</div> </div>
@ -98,19 +97,7 @@
</div> </div>
<div class="abn"> {% include 'client/includes/banners/header.html' %}
{% block header_banner %}
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- 468 на 60 -->
<ins class="adsbygoogle"
style="display:inline-block;width:468px;height:60px"
data-ad-client="ca-pub-5242360491829403"
data-ad-slot="4482648777"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
{% endblock %}
</div>
</div> </div>

@ -48,6 +48,13 @@
</div> </div>
</div> </div>
</li> </li>
{% if forloop.counter == 5 or objects|length < 5 %}
{% include 'client/includes/banners/catalog_inner_2.html' %}
{% endif %}
{% if forloop.counter == 8 %}
{% include 'client/includes/banners/catalog_inner.html' %}
{%endif %}
{% endfor %} {% endfor %}
</ul> </ul>
{% endwith %} {% endwith %}

@ -287,6 +287,10 @@
<div class="m-article"> <div class="m-article">
{% include 'client/includes/booking_block.html' with city=place.city place=place %} {% include 'client/includes/booking_block.html' with city=place.city place=place %}
</div> </div>
<div class="clearfix">
<hr />
{% include 'client/includes/banners/detail_inner.html' %}
</div>
{% if place.get_nearest_places %} {% if place.get_nearest_places %}
<div class="e-cat"> <div class="e-cat">
<div class="sect-title">{% trans 'Ближайшие выставочные центры' %}</div> <div class="sect-title">{% trans 'Ближайшие выставочные центры' %}</div>

@ -55,22 +55,7 @@
</div> </div>
</div> </div>
{% include 'client/includes/banners/main_page_inner.html' %}
<div class="abn">
{% block menu_banner %}
{% comment %}
{% if False|random3 == 1 %}
<a target="_blank" href="/redirect/redirect/31/"><img src="{% static 'client/img/partners/expomap-seminars-01.jpg' %}" alt="" /></a>
{% else %}
{% if False|random3 == 2 %}
<a target="_blank" href="/redirect/redirect/32/"><img src="{% static 'client/img/partners/expomap-seminars-02.gif' %}" alt="" /></a>
{% else %}
<a target="_blank" href="/redirect/redirect/33/"><img src="{% static 'client/img/partners/expomap-seminars-03.gif' %}" alt="" /></a>
{% endif %}
{% endif %}
{% endcomment %}
{% endblock %}
</div>
</div> </div>
</div> </div>
@ -159,12 +144,6 @@
<div class="mcl"> <div class="mcl">
<div class="mp-reviews-wrap clearfix"> <div class="mp-reviews-wrap clearfix">
{% include 'client/includes/index/blogs.html' with blogs=blogs %} {% include 'client/includes/index/blogs.html' with blogs=blogs %}
{% comment %}
<!-- task EXPO-145-->
<div class="sbnr">
<div class="sbnr-wrap"><a href="#"><img src="{% static 'client/img/_del-temp/bnrs.jpg' %}" alt="" /></a></div>
</div>
{% endcomment %}
</div> </div>
</div> </div>
</div> </div>

@ -1,4 +1,4 @@
{% extends 'base_page.html' %} {% extends 'client/base_catalog.html' %}
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}

@ -18,7 +18,7 @@
{% endblock %} {% endblock %}
{% block content_list %} {% block content_list %}
{% include 'includes/place/place_list.html' with object_list=object_list %} {% include 'client/includes/place/place_list.html' with object_list=object_list %}
{% endblock %} {% endblock %}
{% block paginator %} {% block paginator %}

@ -97,6 +97,7 @@ Disallow: /*/serv-visa-info.php
Disallow: /*/serv-uchastie-info.php Disallow: /*/serv-uchastie-info.php
Disallow: /*/serv-catalogue-info.php Disallow: /*/serv-catalogue-info.php
Disallow: /*/serv-catalogs-info.php Disallow: /*/serv-catalogs-info.php
Disallow: /expo-b/
Sitemap: http://expomap.ru/sitemap.xml Sitemap: http://expomap.ru/sitemap.xml
User-agent: Googlebot User-agent: Googlebot
@ -198,6 +199,7 @@ Disallow: /*/serv-visa-info.php
Disallow: /*/serv-uchastie-info.php Disallow: /*/serv-uchastie-info.php
Disallow: /*/serv-catalogue-info.php Disallow: /*/serv-catalogue-info.php
Disallow: /*/serv-catalogs-info.php Disallow: /*/serv-catalogs-info.php
Disallow: /expo-b/
Sitemap: http://expomap.ru/sitemap.xml Sitemap: http://expomap.ru/sitemap.xml
User-agent: Yandex User-agent: Yandex
@ -299,5 +301,6 @@ Disallow: /*/serv-visa-info.php
Disallow: /*/serv-uchastie-info.php Disallow: /*/serv-uchastie-info.php
Disallow: /*/serv-catalogue-info.php Disallow: /*/serv-catalogue-info.php
Disallow: /*/serv-catalogs-info.php Disallow: /*/serv-catalogs-info.php
Disallow: /expo-b/
Host: expomap.ru Host: expomap.ru
Sitemap: http://expomap.ru/sitemap.xml Sitemap: http://expomap.ru/sitemap.xml

@ -0,0 +1,87 @@
(function () {
"use strict";
var API_URL_ROOT = "/expo-b/get-banners/";
var getUrl = function () {
var data = window.sendData;
if (data instanceof Object) {
var search = [];
for (var key in data) {
if (data.hasOwnProperty(key)) {
var value = data[key];
if (value instanceof Array) {
for (var i = 0, l = value.length; i < l; i++) {
search.push(encodeURIComponent(key) + "=" + encodeURIComponent(value[i]));
}
} else {
search.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
}
}
}
if (search.length) {
return API_URL_ROOT + "?" + search.join("&");
}
}
return API_URL_ROOT;
};
var getBanners = function (url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function (event) {
if (event.target.readyState === 4) {
if (event.target.status === 200) {
try {
callback(JSON.parse(event.target.responseText));
} catch (error) {
// do nothing
}
}
}
};
xhr.send();
};
var addBanner = function (banner) {
var parent = document.getElementById(banner.id);
if (parent) {
if (banner.is_img) {
var a = document.createElement("a");
a.href = banner.url;
var img = document.createElement("img");
img.src = banner.img;
img.alt = banner.alt;
a.appendChild(img);
parent.appendChild(a);
} else if (banner.is_html) {
parent.innerHTML = banner.text;
}
}
};
var insertBanners = function (data) {
if (data instanceof Array) {
for (var i = 0, l = data.length; i < l; i++) {
addBanner(data[i]);
}
}
};
var main = function () {
getBanners(getUrl(), insertBanners);
};
window.addEventListener("load", main);
})();

@ -1,4 +1,4 @@
{% extends "client/base_page.html" %} {% extends "client/base_catalog.html" %}
{% block title %}Email confirmation{% endblock %} {% block title %}Email confirmation{% endblock %}

@ -1,4 +1,4 @@
{% extends "client/base_page.html" %} {% extends "client/base_catalog.html" %}
{% block title %}Registration complete{% endblock %} {% block title %}Registration complete{% endblock %}

Loading…
Cancel
Save