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

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

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

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

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

@ -16,6 +16,7 @@ urlpatterns = patterns('',
url(r'^profile/company/$', login_required(ProfileCompanyView.as_view())), url(r'^profile/company/$', login_required(ProfileCompanyView.as_view())),
url(r'^profile/settings/$', login_required(SettingsView.as_view())), url(r'^profile/settings/$', login_required(SettingsView.as_view())),
url(r'^profile/calendar/remove/$', 'accounts.views.remove_from_calendar'), url(r'^profile/calendar/remove/$', 'accounts.views.remove_from_calendar'),
url(r'^profile/calendar/export/$', 'core.views.download_workbook'),
url(r'^profile/calendar/$', login_required(CalendarView.as_view())), url(r'^profile/calendar/$', login_required(CalendarView.as_view())),
url(r'^profile/feed/page/(?P<page>\d+)/$', Feed.as_view()), url(r'^profile/feed/page/(?P<page>\d+)/$', Feed.as_view()),
url(r'^profile/feed/$', login_required(Feed.as_view())), url(r'^profile/feed/$', login_required(Feed.as_view())),
@ -28,6 +29,7 @@ urlpatterns = patterns('',
url(r'^user/(?P<url>.*)/events/(?P<page>\d+)/$', UserView.as_view()), url(r'^user/(?P<url>.*)/events/(?P<page>\d+)/$', UserView.as_view()),
url(r'^user/(?P<url>.*)/events/$', UserView.as_view()), url(r'^user/(?P<url>.*)/events/$', UserView.as_view()),
url(r'^user/(?P<url>.*)/$', UserView.as_view()), url(r'^user/(?P<url>.*)/$', UserView.as_view()),
url(r'^inactive-user/$', 'registration.backends.default.views.inactive_user_message'),
#url(r'^profile/messages/(?P<user>.*)/$', login_required(MessagesView.as_view())), #url(r'^profile/messages/(?P<user>.*)/$', login_required(MessagesView.as_view())),
#url(r'^profile/messages/$', login_required(MessagesView.as_view())), #url(r'^profile/messages/$', login_required(MessagesView.as_view())),

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

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

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

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

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

@ -7,13 +7,13 @@ from hvad.models import TranslationManager
class CountryManager(TranslationManager): class CountryManager(TranslationManager):
cache_time = 600 cache_time = 600
'''
def all(self): def all(self):
""" """
hack hack
""" """
return super(TranslationManager, self).all().filter(translations__language_code=lang()).order_by('translations__name') return super(TranslationManager, self).all().filter(translations__language_code=lang()).order_by('translations__name')
'''
def safe_get(self, **kwargs): def safe_get(self, **kwargs):
model = self.model model = self.model
try: try:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -155,6 +155,9 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin):
max_open_area = models.PositiveIntegerField(verbose_name='Максимальная цена открытой площади', 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()

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

@ -151,6 +151,7 @@ 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)
@ -167,6 +168,7 @@ 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')
@ -375,6 +377,11 @@ 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 +392,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):
@ -423,10 +434,11 @@ class ExpoThemeCatalog(ExpoCatalog):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ExpoThemeCatalog, self).get_context_data(**kwargs) context = super(ExpoThemeCatalog, self).get_context_data(**kwargs)
if self.country: if self.country:
context['country'] = self.country context['country'] = str(self.country.id)
if self.city: if self.city:
context['city'] = self.city context['city'] = str(self.city.id)
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
@ -449,6 +461,8 @@ 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

@ -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(';')

@ -11,13 +11,13 @@ class ExpoManager(TranslationManager):
def upcoming(self): def upcoming(self):
return self.language().select_related('country', 'city', 'place').filter(data_begin__gte=datetime.datetime.now().date()).order_by('data_begin') return self.language().select_related('country', 'city', 'place').filter(data_begin__gte=datetime.datetime.now().date()).order_by('data_begin')
"""
def all(self, lang=None): def all(self, lang=None):
if lang: if lang:
return super(ExpoManager, self).language(lang).all().order_by('name') return super(ExpoManager, self).language(lang).all().order_by('name')
else: else:
return super(ExpoManager, self).language(get_language()).all().order_by('name') return super(ExpoManager, self).language(get_language()).all().order_by('name')
"""
def safe_get(self, **kwargs): def safe_get(self, **kwargs):
model = self.model model = self.model
try: try:

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

@ -239,7 +239,6 @@ class ExpositionSearchForm(AbstactSearchForm):
required=False, widget=forms.CheckboxSelectMultiple()) required=False, widget=forms.CheckboxSelectMultiple())
tg = forms.CharField(label=_(u'Теги'), required=False, widget=forms.CheckboxSelectMultiple()) tg = forms.CharField(label=_(u'Теги'), required=False, widget=forms.CheckboxSelectMultiple())
#co = forms.CharField(label=_(u'Страна'), required=False, widget=forms.CheckboxSelectMultiple()) #co = forms.CharField(label=_(u'Страна'), required=False, widget=forms.CheckboxSelectMultiple())
#tg = forms.CharField(label=_(u'Теги'), required=False, widget=forms.CheckboxSelectMultiple())
area = forms.MultipleChoiceField(label=_(u'Регион'), area = forms.MultipleChoiceField(label=_(u'Регион'),
choices=[(item.id, item.name) for item in Area.objects.language().all()], choices=[(item.id, item.name) for item in Area.objects.language().all()],

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -17,6 +17,7 @@
<hr /> <hr />
{% include 'client/includes/online_consult.html' %} {% include 'client/includes/online_consult.html' %}
{% include 'client/includes/banners/aside_1.html' %}
{% block aside_banner1 %} {% block aside_banner1 %}
{% if theme_for_filter.id == 27 or theme_for_filter.id == 9 or theme_for_filter.id == 48 %} {% if theme_for_filter.id == 27 or theme_for_filter.id == 9 or theme_for_filter.id == 48 %}
@ -52,17 +53,19 @@
{% endblock %} {% endblock %}
{% include 'client/includes/side_confs.html' %} {% include 'client/includes/side_confs.html' %}
<hr /> <hr />
{% include 'client/includes/banner_blocks/aside2.html' %} {% include 'client/includes/banners/aside_2.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">
@ -70,7 +73,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 %}
@ -100,12 +103,10 @@
{% endblock %} {% endblock %}
</div> </div>
{% block content_text %} {% block seo_text_ %}
{% comment %} {% if seo_text %}
{% with filter=filter %} {% include 'client/includes/seo_text.html' with object=seo_text %}
{% include 'includes/event_list_description.html' %} {% endif %}
{% endwith %}
{% endcomment %}
{% endblock %} {% endblock %}
{% endblock %} {% endblock %}

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

@ -77,41 +77,17 @@ This template include basic anf main styles and js files,
socialInputMask:['http://','https://'] socialInputMask:['http://','https://']
}); });
</script> </script>
<!-- Yandex.Metrika counter -->
<script type="text/javascript"> <!--test expo_b -->
(function (d, w, c) { <script>
(w[c] = w[c] || []).push(function() { window.sendData = {
try { "theme": [{% for item in themes %}{{ item }}{% endfor %}],
w.yaCounter21606697 = new Ya.Metrika( "country": "{{ country }}",
{id:21606697, webvisor:true, clickmap:true, trackLinks:true, accurateTrackBounce:true} "city": "{{ city }}",
); "tag": "{{ tag }}"
} catch(e) { } };
}); </script>
var n = d.getElementsByTagName("script")[0], <script type="text/javascript" src="{% static 'client/js/banners.js' %}"></script>
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>
</head> </head>
<body {% block body_class %}{% endblock %}> <body {% block body_class %}{% endblock %}>
@ -232,14 +208,16 @@ This template include basic anf main styles and js files,
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{# if user doesnt have url- show form #} {# if user doesnt have url- show form #}
{% if 'partial_pipeline' not in request.session %}
{% include 'client/popups/acquire_email.html' %}
{% endif %}
{% if not request.user.is_anonymous %} {% if not request.user.is_anonymous %}
{% if not request.user.url %} {% if not request.user.url %}
{% include 'client/popups/user_information.html' with form=reg_complete %} {% include 'client/popups/user_information.html' with form=reg_complete %}
{% if request.GET.debug == '1' %} {% if request.GET.debug == '1' %}
<script src="{% static 'client/js/_modules/block.registration.completion.js' %}"></script> <script src="{% static 'client/js/_modules/block.registration.completion.js' %}"></script>
{% else %} {% else %}
<script src="{% static 'client/js_min/_modules/block.registration.completion.min.js' %}"></script> <script type="text/javascript" src="{% static 'client/js_min/_modules/block.registration.completion.min.js' %}"></script>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}

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

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

@ -17,10 +17,10 @@
{% endblock %} {% 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 %}

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

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

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

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

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

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

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

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

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

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

@ -29,11 +29,11 @@
<div class="dsc-text">{{ exposition.discount_description|safe|linebreaks }}</div> <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">

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

@ -3,13 +3,14 @@
{% load template_filters %} {% 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 }}
@ -104,30 +105,7 @@
{% 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 %}

@ -208,29 +208,7 @@
<div class="clearfix"> <div class="clearfix">
<hr /> <hr />
<script type="text/javascript"> {% include 'client/includes/banners/detail_inner.html' %}
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> </div>
<hr /> <hr />

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

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

Loading…
Cancel
Save