diff --git a/expobanner/admin.py b/expobanner/admin.py new file mode 100644 index 00000000..d1273215 --- /dev/null +++ b/expobanner/admin.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +from django.views.generic import TemplateView, CreateView, ListView, UpdateView +from django.conf import settings +from expobanner.models import URL, BannerGroup, Banner +from expobanner.forms import UrlCreateForm, BannerCreateGroupForm, BannerCreateForm, BannerGroupUpdateForm + + +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'Список банеров' + +# 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 \ No newline at end of file diff --git a/expobanner/admin_urls.py b/expobanner/admin_urls.py new file mode 100644 index 00000000..db31823e --- /dev/null +++ b/expobanner/admin_urls.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from django.conf.urls import patterns, url +from expobanner.admin import * + +urlpatterns = patterns('expobanner.admin', + 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\d+)/edit/$', UrlUpdate.as_view(), name='expobanner-update_url'), + url(r'^banners/group/(?P\d+)/edit/$', BannerGroupUpdate.as_view(), name='expobanner-update_group'), + url(r'^banners/banner/(?P\d+)/edit/$', BannerUpdate.as_view(), name='expobanner-update_banner'), + + +) \ No newline at end of file diff --git a/expobanner/forms.py b/expobanner/forms.py new file mode 100644 index 00000000..64ef9f5a --- /dev/null +++ b/expobanner/forms.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +from django import forms +from expobanner.models import URL, BannerGroup, Banner +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'] + + def clean_theme(self): + theme = self.cleaned_data['theme'] + if not theme: + return None + try: + return Theme.objects.filter(id=theme) + except Theme.DoesNotExist: + return None + + def clean_country(self): + country = self.cleaned_data['country'] + if not country: + return None + try: + return Country.objects.get(id=country) + except Country.DoesNotExist: + return None + + def clean_tag(self): + tag = self.cleaned_data['tag'] + if not tag: + return None + try: + return Tag.objects.get(id=tag) + except Tag.DoesNotExist: + return None + + def clean_city(self): + city = self.cleaned_data['city'] + if not city: + return None + try: + return City.objects.get(id=city) + except City.DoesNotExist: + return None \ No newline at end of file diff --git a/expobanner/managers.py b/expobanner/managers.py index 78887ffa..a872c61f 100644 --- a/expobanner/managers.py +++ b/expobanner/managers.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -* from random import choice, shuffle from django.db import models +from django.core.cache import cache class BiasedManager(models.Manager): @@ -19,3 +20,13 @@ class BiasedManager(models.Manager): result = self.by_time(**kwargs) shuffle(result) return result + +class BannerGroupCached(models.Manager): + def all(self): + key = 'banner_group_all' + result = cache.get(key) + if not result: + result = list(self.filter()) + cache.set(key, result, 90) + return result + diff --git a/expobanner/models.py b/expobanner/models.py index 1984fcc3..c0e6a6cc 100644 --- a/expobanner/models.py +++ b/expobanner/models.py @@ -1,21 +1,22 @@ +# -*- coding: utf-8 -*- import hashlib -from datetime import datetime +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 .managers import BiasedManager +from .managers import BiasedManager, BannerGroupCached class URL(models.Model): - title = models.CharField(verbose_name=_('Title'), max_length=256) - url = models.CharField(verbose_name=_('URL or URL RegEx'), max_length=2048) - regex = models.BooleanField(verbose_name=_('RegEx'), default=False) + 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=_('Public'), default=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) @@ -27,17 +28,21 @@ class URL(models.Model): 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=_('Name'), max_length=255) - slug = models.SlugField(verbose_name=_('Slug'), unique=True) - width = models.PositiveSmallIntegerField(verbose_name=_('Width'), default=0) - height = models.PositiveSmallIntegerField(verbose_name=_('Height'), default=0) - speed = models.PositiveSmallIntegerField(verbose_name=_('Speed'), default=2000) + 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=_('Public'), default=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) + cached = BannerGroupCached() def size(self): return '%sx%s' % (self.width, self.height) @@ -50,20 +55,23 @@ class BannerGroup (models.Model): 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): objects = BiasedManager() - title = models.CharField(verbose_name=_('Title'), max_length=255, blank=True) + 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=_('Text'), blank=True, null=True) - img = models.FileField(verbose_name=_('Image'), upload_to='expo_upload', blank=True, null=True) - url = models.CharField(verbose_name=_('URL'), max_length=1024) + 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) - sort = models.PositiveSmallIntegerField(verbose_name=_('Sort'), default=500) + sort = models.PositiveSmallIntegerField(verbose_name=u'Сорт', default=500) - group = models.ForeignKey(BannerGroup, related_name='banners', verbose_name=_('Group')) + 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.'), @@ -71,14 +79,25 @@ class Banner(models.Model): ) urls = models.ManyToManyField(URL, related_name='url_banners', verbose_name=_('URLs'), null=True, blank=True) - html = models.BooleanField(verbose_name=_('Is HTML?'), default=False) - flash = models.BooleanField(verbose_name=_('Is Flash?'), default=False) + html = models.BooleanField(verbose_name=_('HTML?'), default=False) + flash = models.BooleanField(verbose_name=_('Flash?'), default=False) + paid = models.BooleanField(verbose_name=_('Is Paid event link?'), default=False) - public = models.BooleanField(verbose_name=_('Public'), default=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) + theme = models.ForeignKey('theme.Theme', blank=True, null=True, verbose_name=u'Тематика') + tag = models.ForeignKey('theme.Tag', blank=True, null=True, verbose_name=u'Тег') + country = models.ForeignKey('country.Country', blank=True, null=True, verbose_name=u'Страна') + city = models.ForeignKey('city.City', blank=True, null=True, verbose_name=u'Город') + + + 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 @@ -168,3 +187,50 @@ class LogStat(models.Model): def __unicode__(self): return '%s - (%s)' % (self.banner, self.date) + + +# ------------------ +class Paid(models.Model): + tickets = models.ForeignKey(Banner, related_name='paid_tickets') + participation = models.ForeignKey(Banner, related_name='paid_participation') + official = models.ForeignKey(Banner, related_name='paid_official') + logo = models.ImageField(upload_to='/')# !!!!! + organiser = models.CharField(max_length=100) + active = models.BooleanField(default=True) + stat_pswd = models.CharField(max_length=16) + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + +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) + + +class Top(models.Model): + catalog = models.CharField(max_length=16) + position = models.PositiveIntegerField(blank=True, null=True) + theme = models.ManyToManyField('theme.Theme', blank=True, null=True) + excluded_tags = models.ManyToManyField('theme.Tag', blank=True, null=True) + country = models.ManyToManyField('country.Country', blank=True, null=True) + excluded_cities = models.ManyToManyField('city.City', blank=True, null=True) + fr = models.DateField(default=date.today()) + to = models.DateField(blank=True, null=True) + stat_pswd = models.CharField(max_length=16) + + 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) \ No newline at end of file diff --git a/expobanner/urls.py b/expobanner/urls.py index 97f7f95e..4371bc5f 100644 --- a/expobanner/urls.py +++ b/expobanner/urls.py @@ -5,4 +5,7 @@ from . import views urlpatterns = [ url(r'^click/(?P\d{1,4})/(?P[-\w]+)/$', views.click, name='banner_click'), url(r'^view/(?P\d+)/(?P[-\w]+)/$', views.view, name='banner_view'), + + # + url(r'^get-banners/$', views.get_banners), ] diff --git a/expobanner/views.py b/expobanner/views.py index 8874f598..94709042 100644 --- a/expobanner/views.py +++ b/expobanner/views.py @@ -1,5 +1,8 @@ +# -*- coding: utf-8 -*- +import json +from django.http import HttpResponse from django.shortcuts import redirect, get_object_or_404 -from .models import Banner +from .models import Banner, BannerGroup def click(request, banner_id, key): @@ -12,3 +15,32 @@ def view(request, banner_id, key): banner = get_object_or_404(Banner, pk=banner_id) banner.log(request, 1, key) return redirect(banner.img.url) + + +def get_client_ip(request): + x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') + if x_forwarded_for: + ip = x_forwarded_for.split(',')[0] + else: + ip = request.META.get('REMOTE_ADDR') + return ip + +def get_banners(request): + url = request.GET.get('url', '/') + theme = request.GET.get('theme') + country = request.GET.get('country') + city = request.GET.get('city') + tag = request.GET.get('tag') + ip = get_client_ip(request) + params = {'url': url, + 'theme': theme, + 'tag': tag, + 'country': country, + 'city': city, + 'ip': ip} + b = Banner.objects.get(id=1) + result = [{'url': b.url, 'id': 'expo_b_%d'%b.id, 'is_html': b.html, + 'is_flash': b.flash, 'is_img': True, 'html': b.text, 'img': b.img.url}] + return HttpResponse(json.dumps(result, indent=4), content_type='application/json') + + diff --git a/proj/admin_urls.py b/proj/admin_urls.py index 0e66313d..c34d8274 100644 --- a/proj/admin_urls.py +++ b/proj/admin_urls.py @@ -18,6 +18,7 @@ urlpatterns = required( url(r'^company/', include('company.admin_urls')), url(r'^conference/', include('conference.admin_urls')), url(r'^country/', include('country.admin_urls')), + url(r'^expobanners/', include('expobanner.admin_urls')), url(r'^exposition/', include('exposition.admin_urls')), url(r'^news/', include('news.admin_urls')), url(r'^organiser/', include('organiser.admin_urls')), diff --git a/proj/urls.py b/proj/urls.py index c73029c6..a8906dc1 100644 --- a/proj/urls.py +++ b/proj/urls.py @@ -43,6 +43,7 @@ urlpatterns = patterns('', url(r'^theme/', include('theme.urls')), url(r'^places/', include('place_exposition.urls')), url(r'^translators/', include('translator.urls')), + url(r'^expo-b/', include('expobanner.urls')), url(r'^', include('accounts.urls')), url(r'^', include('exposition.urls')), url(r'^', include('settings.conference_old_urls')), # conference redirects from old version diff --git a/settings/management/commands/do_inflect.py b/settings/management/commands/do_inflect.py index 601a69a3..c226f08a 100644 --- a/settings/management/commands/do_inflect.py +++ b/settings/management/commands/do_inflect.py @@ -8,7 +8,7 @@ from city.models import City CITIES = settings.MEDIA_ROOT+'/import/cities_inflect.xls' TAGS = settings.MEDIA_ROOT+'/import/tags_inflect.xls' - +import inspect, os class Command(BaseCommand): def handle(self, *args, **options): diff --git a/templates/admin/expobanner/banners_control.html b/templates/admin/expobanner/banners_control.html new file mode 100644 index 00000000..e307cecd --- /dev/null +++ b/templates/admin/expobanner/banners_control.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} + + +{% block body %} +
+
+
+

Создание

+
+ +
+ +
+
+

Список

+ +
+ +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/admin/expobanner/default_form.html b/templates/admin/expobanner/default_form.html new file mode 100644 index 00000000..30c72263 --- /dev/null +++ b/templates/admin/expobanner/default_form.html @@ -0,0 +1,59 @@ +{% extends 'base.html' %} +{% load static %} + +{% block scripts %} + + + +{% endblock %} + +{% block body %} +
{% csrf_token %} +
+ +
+
+

{{ form.verbose }}

+
+
+ {% for field in form %} +
+ +
{{ field }} + {{ field.errors }} +
+
+ {% endfor %} +
+
+
+ +
+ + +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/admin/expobanner/default_list.html b/templates/admin/expobanner/default_list.html new file mode 100644 index 00000000..5b8696c6 --- /dev/null +++ b/templates/admin/expobanner/default_list.html @@ -0,0 +1,34 @@ +{% extends 'base.html' %} + +{% block body %} + +
+
+

{{ verbose }}

+
+
+ {% block list_table %} + + + + + + + + + + {% for item in object_list %} + + + + + {% endfor %} + +
Объект 
{{ item }}Изменить
+ {% endblock %} +
+ {# pagination #} + {% include 'admin/includes/admin_pagination.html' with page_obj=object_list %} +
+ +{% endblock %} \ No newline at end of file diff --git a/templates/admin/includes/admin_nav.html b/templates/admin/includes/admin_nav.html index 7f1ec5ed..9f33389b 100644 --- a/templates/admin/includes/admin_nav.html +++ b/templates/admin/includes/admin_nav.html @@ -105,6 +105,13 @@ + + diff --git a/templates/client/base_catalog.html b/templates/client/base_catalog.html index 42d7fcaa..b15afa98 100644 --- a/templates/client/base_catalog.html +++ b/templates/client/base_catalog.html @@ -101,7 +101,7 @@ {% block content_text %} {% comment %} {% with filter=filter %} - {% include 'includes/event_list_description.html' %} + {% include 'includes/event_list_description.html' with ceo_text=ceo_text %} {% endwith %} {% endcomment %} diff --git a/theme/admin.py b/theme/admin.py index 593e18f8..da323984 100644 --- a/theme/admin.py +++ b/theme/admin.py @@ -147,20 +147,17 @@ def search_tag(request): else: qs = Tag.objects.filter(theme__id__in=theme_ids, translations__name__contains=term) - tags = [{'id': tag.id, 'label': '%s(%s)'%(tag.name, tag.theme.name)} for tag in qs] + return HttpResponse(json.dumps(tags), content_type='application/json') - """ - tags = [] - for id in theme_ids: - if not term: - t = Tag.objects.filter(theme__id=id) - else: - t = Tag.objects.filter(theme__id=id, translations__name__contains=term) - cur_theme_tag = [{'id': tag.id, 'label': '%s(%s)'%(tag.name, tag.theme.name)} for tag in t] - tags = tags +cur_theme_tag - """ +def search2(request): + term = request.GET['term'] + if not term: + qs = Tag.objects.filter().order_by('translations__name')[:50] + else: + qs = Tag.objects.filter(translations__name__contains=term)[:50] + tags = [{'id': tag.id, 'text': '%s(%s)'%(tag.name, tag.theme.name)} for tag in qs] return HttpResponse(json.dumps(tags), content_type='application/json') diff --git a/theme/admin_urls.py b/theme/admin_urls.py index a2b34061..c1803d4f 100644 --- a/theme/admin_urls.py +++ b/theme/admin_urls.py @@ -16,4 +16,5 @@ urlpatterns = patterns('theme.admin', url(r'^theme/all/$', ThemeListView.as_view()), url(r'^tag/all/$', TagListView.as_view()), url(r'^tag/search/$', 'search_tag'), + url(r'^tag/search-without-theme/$', 'search2'), )