commit
da15bf65a4
149 changed files with 4891 additions and 389 deletions
@ -1,18 +1,36 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
from django.utils import translation |
||||||
from haystack import indexes |
from haystack import indexes |
||||||
from models import City |
from models import City |
||||||
|
from functions.search_mixin import ExpoSearchMixin |
||||||
|
|
||||||
""" |
|
||||||
class CityIndex(indexes.SearchIndex, indexes.Indexable): |
class CountryIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin): |
||||||
text = indexes.CharField(document=True, use_template=True) |
text = indexes.CharField(document=True, use_template=True) |
||||||
translations = indexes.MultiValueField() |
url = indexes.CharField() |
||||||
#name = indexes.CharField(model_attr='translations__name') |
content_auto = indexes.EdgeNgramField() |
||||||
|
form_name = indexes.CharField() |
||||||
|
# translated fields |
||||||
|
name_en = indexes.CharField() |
||||||
|
name_ru = indexes.CharField() |
||||||
|
catalog_name_en = indexes.CharField() |
||||||
|
catalog_name_ru = indexes.CharField() |
||||||
|
|
||||||
|
def prepare_form_name(self, obj): |
||||||
|
return 'ci' |
||||||
|
|
||||||
|
def prepare_catalog_name_en(self, obj): |
||||||
|
return u'Cities' |
||||||
|
|
||||||
def prepare_translations(self, obj): |
def prepare_catalog_name_ru(self, obj): |
||||||
return [tr.name for tr in obj.translations.all()] |
return u'Города' |
||||||
|
|
||||||
def get_model(self): |
def get_model(self): |
||||||
return City |
return City |
||||||
|
|
||||||
def index_queryset(self, using=None): |
def index_queryset(self, using=None): |
||||||
return self.get_model().objects.filter() |
|
||||||
""" |
return self.get_model().used.all() |
||||||
|
|
||||||
|
def get_updated_field(self): |
||||||
|
return 'modified' |
||||||
@ -0,0 +1,62 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
from django.utils import translation |
||||||
|
from haystack import indexes |
||||||
|
from models import Country, Area |
||||||
|
from functions.search_mixin import ExpoSearchMixin |
||||||
|
|
||||||
|
|
||||||
|
class CountryIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin): |
||||||
|
text = indexes.CharField(document=True, use_template=True) |
||||||
|
url = indexes.CharField() |
||||||
|
content_auto = indexes.EdgeNgramField() |
||||||
|
form_name = indexes.CharField() |
||||||
|
# translated fields |
||||||
|
name_en = indexes.CharField() |
||||||
|
name_ru = indexes.CharField() |
||||||
|
catalog_name_en = indexes.CharField() |
||||||
|
catalog_name_ru = indexes.CharField() |
||||||
|
|
||||||
|
def prepare_form_name(self, obj): |
||||||
|
return 'co' |
||||||
|
|
||||||
|
def prepare_catalog_name_en(self, obj): |
||||||
|
return u'Countries' |
||||||
|
|
||||||
|
def prepare_catalog_name_ru(self, obj): |
||||||
|
return u'Страны' |
||||||
|
|
||||||
|
def get_model(self): |
||||||
|
return Country |
||||||
|
|
||||||
|
def index_queryset(self, using=None): |
||||||
|
|
||||||
|
return self.get_model().objects.countries_for_search() |
||||||
|
|
||||||
|
def get_updated_field(self): |
||||||
|
return 'modified' |
||||||
|
|
||||||
|
class AreaIndex(indexes.SearchIndex, indexes.Indexable, ExpoSearchMixin): |
||||||
|
text = indexes.CharField(document=True, use_template=True) |
||||||
|
content_auto = indexes.EdgeNgramField() |
||||||
|
form_name = indexes.CharField() |
||||||
|
# translated fields |
||||||
|
name_en = indexes.CharField() |
||||||
|
name_ru = indexes.CharField() |
||||||
|
catalog_name_en = indexes.CharField() |
||||||
|
catalog_name_ru = indexes.CharField() |
||||||
|
|
||||||
|
def prepare_form_name(self, obj): |
||||||
|
return 'area' |
||||||
|
|
||||||
|
def prepare_catalog_name_en(self, obj): |
||||||
|
return u'Areas' |
||||||
|
|
||||||
|
def prepare_catalog_name_ru(self, obj): |
||||||
|
return u'Регионы' |
||||||
|
|
||||||
|
def get_model(self): |
||||||
|
return Area |
||||||
|
|
||||||
|
def index_queryset(self, using=None): |
||||||
|
|
||||||
|
return self.get_model().objects.filter() |
||||||
@ -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 |
||||||
@ -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<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'), |
||||||
|
|
||||||
|
|
||||||
|
) |
||||||
@ -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 |
||||||
@ -0,0 +1,32 @@ |
|||||||
|
# -*- coding: utf-8 -* |
||||||
|
from random import choice, shuffle |
||||||
|
from django.db import models |
||||||
|
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 |
||||||
|
|
||||||
|
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 |
||||||
|
|
||||||
@ -0,0 +1,236 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
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 .managers import BiasedManager, BannerGroupCached |
||||||
|
|
||||||
|
|
||||||
|
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) |
||||||
|
|
||||||
|
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) |
||||||
|
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): |
||||||
|
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) |
||||||
|
|
||||||
|
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)] |
||||||
|
) |
||||||
|
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) |
||||||
|
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) |
||||||
|
|
||||||
|
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 |
||||||
|
else: |
||||||
|
key = str(datetime.now()) |
||||||
|
return hashlib.md5(key).hexdigest() |
||||||
|
|
||||||
|
def log(self, request, type, key): |
||||||
|
log = { |
||||||
|
'type': type, |
||||||
|
'key': key, |
||||||
|
'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) |
||||||
|
|
||||||
|
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) |
||||||
|
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) |
||||||
|
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): |
||||||
|
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) |
||||||
@ -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'>〈 </span> |
||||||
|
<span data-direction="next" class='b-slider-nav-next'> 〉</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,11 @@ |
|||||||
|
from django.conf.urls import url |
||||||
|
|
||||||
|
from . import views |
||||||
|
|
||||||
|
urlpatterns = [ |
||||||
|
url(r'^click/(?P<banner_id>\d{1,4})/(?P<key>[-\w]+)/$', views.click, name='banner_click'), |
||||||
|
url(r'^view/(?P<banner_id>\d+)/(?P<key>[-\w]+)/$', views.view, name='banner_view'), |
||||||
|
|
||||||
|
# |
||||||
|
url(r'^get-banners/$', views.get_banners), |
||||||
|
] |
||||||
@ -0,0 +1,46 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
import json |
||||||
|
from django.http import HttpResponse |
||||||
|
from django.shortcuts import redirect, get_object_or_404 |
||||||
|
from .models import Banner, BannerGroup |
||||||
|
|
||||||
|
|
||||||
|
def click(request, banner_id, key): |
||||||
|
banner = get_object_or_404(Banner, pk=banner_id) |
||||||
|
banner.log(request, 2, key) |
||||||
|
return redirect(banner.url) |
||||||
|
|
||||||
|
|
||||||
|
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') |
||||||
|
|
||||||
|
|
||||||
@ -1,20 +1,141 @@ |
|||||||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||||||
|
import MySQLdb |
||||||
|
import os.path |
||||||
|
from MySQLdb.cursors import DictCursor |
||||||
|
from django.utils.translation import activate |
||||||
from django.core.management.base import BaseCommand |
from django.core.management.base import BaseCommand |
||||||
from meta.models import MetaSetting |
from django.conf import settings |
||||||
|
from exposition.models import Exposition |
||||||
|
from theme.models import Theme |
||||||
|
from theme.models import Theme, Tag |
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand): |
class Command(BaseCommand): |
||||||
def handle(self, *args, **options): |
def handle(self, *args, **options): |
||||||
a = MetaSetting.objects.filter(translations__h1__contains='«').count() |
#expos = Exposition.objects.filter(theme__isnull=True, old_url__isnull=False) |
||||||
qs = MetaSetting.objects.language('ru').all() |
db = MySQLdb.connect(host="localhost", |
||||||
for item in qs: |
user="expomap", |
||||||
item.title = item.title.replace(u'«', u'').replace(u'»', u'') |
passwd="7FbLtAGjse", |
||||||
item.description = item.title.replace(u'«', u'').replace(u'»', u'') |
db="old_db", |
||||||
item.h1 = item.h1.replace(u'«', u'').replace(u'»', u'') |
charset='utf8', |
||||||
#item.save() |
cursorclass=DictCursor) |
||||||
|
cursor = db.cursor() |
||||||
|
activate('ru') |
||||||
|
#expos = Exposition.enable.upcoming().filter(logo='') |
||||||
|
expos = Exposition.objects.filter(tag__isnull=True).order_by('-data_end') |
||||||
|
#expo = Exposition.objects.get(old_url='salon-du-livre-2015') |
||||||
|
|
||||||
|
#handle_expo_tag(expo, cursor) |
||||||
|
|
||||||
|
for expo in expos: |
||||||
|
handle_expo_tag(expo, cursor) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
''' |
||||||
|
find_old_id = """ |
||||||
|
SELECT products.products_id |
||||||
|
from products |
||||||
|
LEFT JOIN `products_description` ON products.products_id=products_description.products_id |
||||||
|
WHERE url='%s' |
||||||
|
""" |
||||||
|
|
||||||
|
find_themes = "SELECT categories_id FROM `products_to_categories` WHERE `products_id` =%d" |
||||||
|
''' |
||||||
|
""" |
||||||
|
for expo in expos: |
||||||
|
cursor.execute(find_old_id%expo.old_url) |
||||||
|
old_ids = [item['products_id'] for item in cursor.fetchall()] |
||||||
|
print expo.old_url |
||||||
|
for id in old_ids: |
||||||
|
cursor.execute(find_themes%id) |
||||||
|
themes_ids = [item['categories_id'] for item in cursor.fetchall()] |
||||||
|
print themes_ids |
||||||
|
#if not themes_ids: |
||||||
|
# continue |
||||||
|
|
||||||
|
|
||||||
|
theme_qs = Theme.objects.filter(id__in=themes_ids) |
||||||
|
#expo.theme.add(*theme_qs) |
||||||
|
break |
||||||
|
|
||||||
|
print('----------------------') |
||||||
|
""" |
||||||
|
|
||||||
|
|
||||||
|
def handle_expo_tag(expo, cursor): |
||||||
|
old_url = expo.old_url |
||||||
|
if not old_url: |
||||||
|
return None |
||||||
|
print(old_url) |
||||||
|
find_old = """ |
||||||
|
SELECT products.products_id, url |
||||||
|
from products |
||||||
|
LEFT JOIN `products_description` ON products.products_id=products_description.products_id |
||||||
|
WHERE url='%s' |
||||||
|
""" |
||||||
|
cursor.execute(find_old%old_url) |
||||||
|
result = cursor.fetchone() |
||||||
|
expo_id = result.get('products_id') |
||||||
|
if not expo_id: |
||||||
|
return |
||||||
|
|
||||||
|
find_tag_id = """ |
||||||
|
SELECT tag_id |
||||||
|
FROM `products_tags` |
||||||
|
WHERE `product_id` =%d |
||||||
|
""" |
||||||
|
cursor.execute(find_tag_id%expo_id) |
||||||
|
tags_ids = [str(item['tag_id']) for item in cursor.fetchall()] |
||||||
|
if not tags_ids: |
||||||
|
return None |
||||||
|
find_tag = """ |
||||||
|
SELECT title |
||||||
|
FROM `tags` |
||||||
|
WHERE id in(%s) |
||||||
|
""" |
||||||
|
cursor.execute(find_tag%', '.join(tags_ids)) |
||||||
|
tag_names = [item['title'] for item in cursor.fetchall()] |
||||||
|
if not tag_names: |
||||||
|
return None |
||||||
|
|
||||||
|
themes = [item['id'] for item in expo.theme.all().values('id')] |
||||||
|
qs = Tag.objects.filter(translations__name__in=tag_names, theme__in=themes) |
||||||
|
expo.tag.add(*qs) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def handle_expo(expo, cursor): |
||||||
|
""" |
||||||
|
fixing logos |
||||||
|
|
||||||
|
""" |
||||||
|
if expo.logo: |
||||||
|
return |
||||||
|
|
||||||
|
find_old = """ |
||||||
|
SELECT products.products_id, url, products_img1 as logo |
||||||
|
from products |
||||||
|
LEFT JOIN `products_description` ON products.products_id=products_description.products_id |
||||||
|
WHERE url='%s' |
||||||
|
""" |
||||||
|
cursor.execute(find_old%expo.old_url) |
||||||
|
result = cursor.fetchall() |
||||||
|
if not result: |
||||||
|
return |
||||||
|
logo = result[0]['logo'] |
||||||
|
|
||||||
|
|
||||||
|
if logo: |
||||||
|
logo = logo.replace('..', '') |
||||||
|
|
||||||
|
print(logo) |
||||||
|
print(os.path.isfile(settings.MEDIA_ROOT[:-1]+logo)) |
||||||
|
if (os.path.isfile(settings.MEDIA_ROOT[:-1]+logo)): |
||||||
|
|
||||||
|
expo.logo = logo |
||||||
|
expo.save() |
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,77 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
from django.db import models |
||||||
|
from django.conf import settings |
||||||
|
from django.db.models.fields.files import FieldFile |
||||||
|
from django.db.models.signals import pre_delete |
||||||
|
|
||||||
|
def get_doc_dir(instance, filename): |
||||||
|
from pytils import translit |
||||||
|
return u'import_xls/import/%s' %translit.translify(filename) |
||||||
|
|
||||||
|
|
||||||
|
def file_cleanup(sender, instance, *args, **kwargs): |
||||||
|
''' |
||||||
|
Deletes the file(s) associated with a model instance. The model |
||||||
|
is not saved after deletion of the file(s) since this is meant |
||||||
|
to be used with the pre_delete signal. |
||||||
|
''' |
||||||
|
for field_name, _ in instance.__dict__.iteritems(): |
||||||
|
field = getattr(instance, field_name) |
||||||
|
if issubclass(field.__class__, FieldFile) and field.name: |
||||||
|
field.delete(save=False) |
||||||
|
|
||||||
|
class LogManager(models.Manager): |
||||||
|
def create_log(self, work_file, errors): |
||||||
|
""" |
||||||
|
|
||||||
|
:param work_file: executing file |
||||||
|
:param errors: list of errors ([{'event name':['err1', 'err2']}]) |
||||||
|
:return: object log |
||||||
|
""" |
||||||
|
LOG_DIRECTORY = settings.MEDIA_ROOT+'import_xls/logs/' |
||||||
|
name= '111.txt' |
||||||
|
filename = LOG_DIRECTORY + name |
||||||
|
|
||||||
|
log_file = open(filename, "w") |
||||||
|
for error in errors: |
||||||
|
event_name = ';'.join(error.keys()) |
||||||
|
errs = '' |
||||||
|
for err in error.values(): |
||||||
|
errs += '; '.join(err) |
||||||
|
errs += ';' |
||||||
|
|
||||||
|
log_file.write('%s: %s\n'%(event_name, errs)) |
||||||
|
|
||||||
|
log_file.close() |
||||||
|
#update.log_file.name = 'updates/'+name |
||||||
|
log = Log(work_file=work_file) |
||||||
|
log.log.name = 'import_xls/logs/' + name |
||||||
|
#log = Log.objects.create(work_file=work_file, log=log_file) |
||||||
|
log.save() |
||||||
|
return log |
||||||
|
|
||||||
|
def create_log_name(self, work_file): |
||||||
|
log = Log.objects.create(work_file=work_file) |
||||||
|
LOG_DIRECTORY = settings.MEDIA_ROOT+'import_xls/logs/' |
||||||
|
name= 'log_%d.log'%log.id |
||||||
|
filename = LOG_DIRECTORY + name |
||||||
|
log_file = open(filename, "w").close() |
||||||
|
log.log.name = 'import_xls/logs/' + name |
||||||
|
log.save() |
||||||
|
return log |
||||||
|
|
||||||
|
|
||||||
|
class Log(models.Model): |
||||||
|
work_file = models.FileField(upload_to=get_doc_dir) |
||||||
|
log = models.FileField(upload_to='import_xls/logs/', blank=True) |
||||||
|
type = models.CharField(max_length=10, default='IMPORT') |
||||||
|
created = models.DateTimeField(auto_now_add=True) |
||||||
|
|
||||||
|
objects = models.Manager() |
||||||
|
custom = LogManager() |
||||||
|
|
||||||
|
class Meta: |
||||||
|
ordering = ['-created'] |
||||||
|
|
||||||
|
pre_delete.connect(file_cleanup, sender=Log) |
||||||
|
|
||||||
@ -0,0 +1,47 @@ |
|||||||
|
function make_event_select(id, url, placeholder){ |
||||||
|
$(id).select2({ |
||||||
|
placeholder: placeholder, |
||||||
|
multiple: true, |
||||||
|
ajax: { |
||||||
|
|
||||||
|
url: url, |
||||||
|
width: '550px', |
||||||
|
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 data = []; |
||||||
|
$(element.val().split(",")).each(function(i) { |
||||||
|
var item = this.split(':'); |
||||||
|
data.push({ |
||||||
|
id: item[0], |
||||||
|
text: item[1] |
||||||
|
}); |
||||||
|
}); |
||||||
|
callback(data); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function(){ |
||||||
|
make_event_select('#id_expositions', '/admin/exposition/search/', 'Выставки'); |
||||||
|
make_event_select('#id_conferences', '/admin/conference/search/', 'Конференции'); |
||||||
|
}); |
||||||
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 47 KiB |
@ -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,59 @@ |
|||||||
|
{% 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_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> </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,46 @@ |
|||||||
|
{% extends 'base.html' %} |
||||||
|
{% load static %} |
||||||
|
|
||||||
|
|
||||||
|
{% block body %} |
||||||
|
{% comment %} |
||||||
|
Displays lists of all cities in the table |
||||||
|
and creating buttons which can change each city |
||||||
|
{% endcomment %} |
||||||
|
|
||||||
|
<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> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
{% for item in object_list %} |
||||||
|
<tr> |
||||||
|
<td>{{ item.created|date:"Y-m-d H:m:s" }}</td> |
||||||
|
<td><a href="/admin/log/work_file/{{ item.id }}/">скачать</a></td> |
||||||
|
<td><a href="/admin/log/log/{{ item.id }}/">скачать</a></td> |
||||||
|
<td class="center sorting_1"> |
||||||
|
<a class="btn btn-danger delete" href="/admin/import/log/delete/{{ item.id }}/"> |
||||||
|
<i class="icon-trash icon-white"></i> Удалить |
||||||
|
</a> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
{% endfor %} |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
|
||||||
|
{% include 'admin/includes/admin_pagination.html' with page_obj=objects %} |
||||||
|
|
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,15 @@ |
|||||||
|
{% extends 'base.html' %} |
||||||
|
|
||||||
|
{% block body %} |
||||||
|
|
||||||
|
<form action="" method="post"> {% csrf_token %} |
||||||
|
|
||||||
|
<div class="alert alert-danger"> |
||||||
|
<p>Вы действительно хотите удалить <b>{{ object }}</b>?</p> |
||||||
|
</div> |
||||||
|
<input type="submit" class="btn-primary" value="Да"> |
||||||
|
<a class="btn" href="/admin/import/log/">Нет</a> |
||||||
|
</form> |
||||||
|
|
||||||
|
|
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,78 @@ |
|||||||
|
{% 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> |
||||||
|
|
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block body %} |
||||||
|
|
||||||
|
<form method="post" class="form-horizontal" name="form" id="main_form"> {% csrf_token %} |
||||||
|
<fieldset> |
||||||
|
<legend><i class="icon-edit"></i>Управление услугой {{ object.name }}</legend> |
||||||
|
|
||||||
|
<div class="box span8" > |
||||||
|
<div class="box-header well"> |
||||||
|
<h2><i class="icon-pencil"></i></h2> |
||||||
|
</div> |
||||||
|
<div class="box-content"> |
||||||
|
{# event_type #} |
||||||
|
<div class="control-group {% if form.event_type.errors %}error{% endif %}"> |
||||||
|
<label class="control-label">{{ form.event_type.label }}:</label> |
||||||
|
<div class="controls"> |
||||||
|
{{ form.event_type }} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# country_all #} |
||||||
|
<div class="control-group {% if form.country_all.errors %}error{% endif %}"> |
||||||
|
<label class="control-label">{{ form.country_all.label }}:</label> |
||||||
|
<div class="controls">{{ form.country_all }} |
||||||
|
<span class="help-inline">{{ form.country_all.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# region #} |
||||||
|
<div class="control-group {% if form.region.errors %}error{% endif %}"> |
||||||
|
<label class="control-label">{{ form.region.label }}:</label> |
||||||
|
<div class="controls">{{ form.region }} |
||||||
|
<span class="help-inline">{{ form.region.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# country #} |
||||||
|
<div class="control-group {% if form.country.errors %}error{% endif %}"> |
||||||
|
<label class="control-label">{{ form.country.label }}:</label> |
||||||
|
<div class="controls">{{ form.country }} |
||||||
|
<span class="help-inline">{{ form.country.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{# expositions #} |
||||||
|
<div class="control-group {% if form.expositions.errors %}error{% endif %}"> |
||||||
|
<label class="control-label">{{ form.expositions.label }}:</label> |
||||||
|
<div class="controls">{{ form.expositions }} |
||||||
|
<span class="help-inline">{{ form.expositions.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{# conferences #} |
||||||
|
<div class="control-group {% if form.conferences.errors %}error{% endif %}"> |
||||||
|
<label class="control-label">{{ form.conferences.label }}:</label> |
||||||
|
<div class="controls">{{ form.conferences }} |
||||||
|
<span class="help-inline">{{ form.conferences.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</fieldset> |
||||||
|
</form> |
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block bot_scripts %} |
||||||
|
<script src="{% static 'custom_js/find_events.js' %}"></script> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,39 @@ |
|||||||
|
{% extends 'admin_list.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>id</th> |
||||||
|
<th>Название</th> |
||||||
|
<th> </th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
{% for item in object_list %} |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td>{{ item.id }}</td> |
||||||
|
<td>{{ item.name }}</td> |
||||||
|
|
||||||
|
<td> |
||||||
|
<a class="btn-small btn-info" href="/admin/service/control/{{ item.id }}/"> |
||||||
|
Управлять |
||||||
|
</a> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
|
||||||
|
{% endfor %} |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
{# pagination #} |
||||||
|
{% include 'admin/includes/admin_pagination.html' with page_obj=object_list %} |
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,133 @@ |
|||||||
|
{% extends 'base.html' %} |
||||||
|
{% load static %} |
||||||
|
{# Displays translator form and file form in modal window #} |
||||||
|
|
||||||
|
|
||||||
|
{% 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> |
||||||
|
{# datetimepicker #} |
||||||
|
<link href="{% static 'js/datetimepicker/css/datetimepicker.css' %}" rel="stylesheet"/> |
||||||
|
<script src="{% static 'js/datetimepicker/js/bootstrap-datetimepicker.js' %}"></script> |
||||||
|
<script type="text/javascript"> |
||||||
|
$(document).ready(function(){ |
||||||
|
$('#id_birth').datetimepicker({ |
||||||
|
todayHighlight: true, |
||||||
|
format : 'dd.mm.yyyy', |
||||||
|
minView:2 |
||||||
|
}); |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
|
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block body %} |
||||||
|
<form method="post" class="form-horizontal" enctype="multipart/form-data" name="form1" id="form1"> {% csrf_token %} |
||||||
|
<fieldset> |
||||||
|
<legend><i class="icon-edit"></i>Изменить переводчика(<a target="_blank" href="{{ object.get_translator_url }}">на сайте</a>)</legend> |
||||||
|
|
||||||
|
<div class="box span8" > |
||||||
|
<div class="box-header well"> |
||||||
|
<h2><i class="icon-pencil"></i> Основная информация</h2> |
||||||
|
</div> |
||||||
|
<div class="box-content"> |
||||||
|
{# name #} |
||||||
|
<div class="control-group {% if form_user.first_name.errors %}error{% endif %}"> |
||||||
|
<label class="control-label"><b>{{ form_user.first_name.label }}:</b></label> |
||||||
|
<div class="controls">{{ form_user.first_name }} |
||||||
|
<span class="help-inline">{{ form_user.first_name.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# surname #} |
||||||
|
<div class="control-group {% if form_user.last_name.errors %}error{% endif %}"> |
||||||
|
<label class="control-label"><b>{{ form_user.last_name.label }}:</b></label> |
||||||
|
<div class="controls">{{ form_user.last_name }} |
||||||
|
<span class="help-inline">{{ form_user.last_name.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# country #} |
||||||
|
<div class="control-group {% if form_profile.country.errors %}error{% endif %}"> |
||||||
|
<label class="control-label"><b>{{ form_profile.country.label }}:</b></label> |
||||||
|
<div class="controls">{{ form_profile.country }} |
||||||
|
<span class="help-inline">{{ form_profile.country.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# city #} |
||||||
|
<div class="control-group {% if form_profile.city.errors %}error{% endif %}"> |
||||||
|
<label class="control-label"><b>{{ form_profile.city.label }}:</b></label> |
||||||
|
<div class="controls">{{ form_profile.city }} |
||||||
|
<span class="help-inline">{{ form_profile.city.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# logo #} |
||||||
|
<div class="control-group {% if form_profile.avatar.errors %}error{% endif %}"> |
||||||
|
<label class="control-label"><b>{{ form_profile.avatar.label }}:</b></label> |
||||||
|
<div class="controls">{{ form_profile.avatar }} |
||||||
|
<span class="help-inline">{{ form_profile.avatar.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="box span8" > |
||||||
|
<div class="box-header well"> |
||||||
|
<h2><i class="icon-pencil"></i> Информация по переводчику</h2> |
||||||
|
</div> |
||||||
|
<div class="box-content"> |
||||||
|
|
||||||
|
{# car #} |
||||||
|
<div class="control-group {% if form.car.errors %}error{% endif %}"> |
||||||
|
<label class="control-label"><b>{{ form.car.label }}:</b></label> |
||||||
|
<div class="controls">{{ form.car }} |
||||||
|
<span class="help-inline">{{ form.car.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# birth #} |
||||||
|
<div class="control-group {% if form.birth.errors %}error{% endif %}"> |
||||||
|
<label class="control-label"><b>{{ form.birth.label }}:</b></label> |
||||||
|
<div class="controls">{{ form.birth }} |
||||||
|
<span class="help-inline">{{ form.birth.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{# gender #} |
||||||
|
<div class="control-group {% if form.gender.errors %}error{% endif %}"> |
||||||
|
<label class="control-label"><b>{{ form.gender.label }}:</b></label> |
||||||
|
<div class="controls">{{ form.gender }} |
||||||
|
<span class="help-inline">{{ form.gender.errors }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{# time #} |
||||||
|
|
||||||
|
{% include 'admin/forms/multilang.html' with field='education' form=form languages=languages%} |
||||||
|
{% include 'admin/forms/multilang.html' with field='specialization' form=form languages=languages%} |
||||||
|
{% include 'admin/forms/multilang.html' with field='languages' form=form languages=languages%} |
||||||
|
{% include 'admin/forms/multilang.html' with field='native_language' form=form languages=languages%} |
||||||
|
{% include 'admin/forms/multilang.html' with field='prices' form=form languages=languages%} |
||||||
|
{% include 'admin/forms/multilang.html' with field='discounts' form=form languages=languages%} |
||||||
|
|
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="controls"> |
||||||
|
<input class="btn btn-large btn-primary" type="submit" value="Изменить"> |
||||||
|
<input class="btn btn-large" type="reset" value="Отмена"> |
||||||
|
</div> |
||||||
|
</fieldset> |
||||||
|
</form> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,108 @@ |
|||||||
|
{% extends 'base_catalog.html' %} |
||||||
|
{% load i18n %} |
||||||
|
|
||||||
|
|
||||||
|
{% block bread_scrumbs %} |
||||||
|
|
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block page_title %} |
||||||
|
<div class="bread-crumbs"> |
||||||
|
<a href="/">Главная страница</a> |
||||||
|
<a href="/translators/city/{{ object.url }}/">Города</a> |
||||||
|
<strong>Переводчики {{ object.inflect }}</strong> |
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block content_list %} |
||||||
|
<div class="m-article"> |
||||||
|
<div class="item-wrap place clearfix"> |
||||||
|
<aside> |
||||||
|
<div class="i-pict"> |
||||||
|
{% include 'client/includes/show_logo.html' with obj=object %} |
||||||
|
</div> |
||||||
|
|
||||||
|
{# <a class="button about" href="#">о городе</a> #} |
||||||
|
</aside> |
||||||
|
|
||||||
|
<div class="i-info"> |
||||||
|
<header> |
||||||
|
<div class="i-title">{{ object.name }}</div> |
||||||
|
</header> |
||||||
|
|
||||||
|
<div class="i-descr"> |
||||||
|
<p>Компания Serve Businesses Worldwide предлагает Вам возможность заказать услуги русскоговорящих переводчиков со знанием английского языка практически непосредственно в Великобритании.</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr /> |
||||||
|
|
||||||
|
<div class="i-services country_content"> |
||||||
|
<div class="i-descr"> |
||||||
|
<h4>Коротко о наших преимуществах:</h4> |
||||||
|
<ul class="content_list"> |
||||||
|
<li>Эффективная цена</li> |
||||||
|
<li>Опыт и профессионализм специалистов</li> |
||||||
|
<li>Знание разных менталитетов и психологических аспектов проведения переговоров с зарубежными бизнесменами</li> |
||||||
|
<li>Ориентированность в мировых выставочных комплексах </li> |
||||||
|
<li>Гарантии, отчетность по договору, прозрачные безналичные расчеты в России</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="rq-btn-wrap rq-btn-to-hide"> |
||||||
|
|
||||||
|
<div class="rqb-cols"> |
||||||
|
<div class="rqb-button"> |
||||||
|
<div class="rq-order-button"> |
||||||
|
<div class="rqob-wrap"> |
||||||
|
<div class="rqob-price">от 80 € / день</div> |
||||||
|
<div class="rqob-button"> |
||||||
|
<a class="ob-text" href="#">заказать услугу</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr> |
||||||
|
|
||||||
|
|
||||||
|
<div class="i-staff"> |
||||||
|
<div class="sect-title"><a href="/translators/city/{{ object.url }}/all/">Наши специалисты</a></div> |
||||||
|
|
||||||
|
<div class="i-staff-list"> |
||||||
|
|
||||||
|
<ul> |
||||||
|
{% with object_list=object_list %} |
||||||
|
{% for user in object_list %} |
||||||
|
<li> |
||||||
|
<a href="{{ user.get_translator_url }}"> |
||||||
|
<div class="sl-item clearfix"> |
||||||
|
<div class="sl-pict"> |
||||||
|
{% include 'includes/show_logo.html' with obj=user %} |
||||||
|
</div> |
||||||
|
<div class="sl-info"> |
||||||
|
<div class="sl-info-wrap"> |
||||||
|
<div class="sl-name">{{ user.get_full_name }}</div> |
||||||
|
<div class="sl-position">{{ user.translator.languages }}</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
{% endfor %} |
||||||
|
{% endwith %} |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<a class="button more" href="/translators/city/{{ object.url }}/all/">Все переводчики</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
|
|
||||||
@ -0,0 +1,137 @@ |
|||||||
|
{% extends 'base_catalog.html' %} |
||||||
|
{% load i18n %} |
||||||
|
|
||||||
|
|
||||||
|
{% block bread_scrumbs %} |
||||||
|
<div class="bread-crumbs"> |
||||||
|
<a href="/">Главная страница</a> |
||||||
|
<a href="/translators/country/">Страны</a> |
||||||
|
<strong>Переводчики {{ object.inflect }}</strong> |
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block page_title %} |
||||||
|
|
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block content_list %} |
||||||
|
<div class="m-article"> |
||||||
|
<div class="item-wrap place clearfix"> |
||||||
|
<aside> |
||||||
|
<div class="i-pict">{% include 'client/includes/show_logo.html' with obj=object %}</div> |
||||||
|
{# <a class="button about" href="#">о стране</a> #} |
||||||
|
</aside> |
||||||
|
|
||||||
|
<div class="i-info"> |
||||||
|
<header> |
||||||
|
<div class="i-title">Переводчики {{ object.inflect }}</div> |
||||||
|
</header> |
||||||
|
|
||||||
|
<div class="i-descr"> |
||||||
|
<p>Компания Serve Businesses Worldwide предлагает Вам возможность заказать услуги русскоговорящих переводчиков со знанием английского языка практически непосредственно в Великобритании.</p> |
||||||
|
<p>Ниже приведен список наиболее часто востребованных территориальных направлений для оказания услуг перевода в Великобритании. Приведенный перечень не является исчерпывающим, поэтому, если Вы не нашли нужный Вам город, обратитесь к нашим консультантам. </p> |
||||||
|
</div> |
||||||
|
<br> |
||||||
|
{% if object.latitude and object.longitude %} |
||||||
|
<div class="i-address map-opened country_map"> |
||||||
|
|
||||||
|
<div class="i-map"> |
||||||
|
<!-- позиция для карты задается в атрибуте data-coords --> |
||||||
|
<div class="map-canvas" id="map-canvas" data-coords="{{ object.latitude }},{{ object.longitude }}" ></div> |
||||||
|
<div class="close-map"><a class="toggle-map" href="#">Скрыть карту</a></div> |
||||||
|
</div> |
||||||
|
<header> |
||||||
|
<div class="show-map show-map_1"><a class="toggle-map" href="#">Раскрыть карту</a></div> |
||||||
|
</header> |
||||||
|
</div> |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr /> |
||||||
|
|
||||||
|
{% if object.big_cities.exists %} |
||||||
|
{% with cities=object.big_cities.all %} |
||||||
|
<div class="country_towns"> |
||||||
|
<h4>Крупные города:</h4> |
||||||
|
<table> |
||||||
|
<tr> |
||||||
|
<td> |
||||||
|
<ul> |
||||||
|
{% for city in cities %} |
||||||
|
<li><a href="/translators/city/{{ city.url }}/" title="">{{ city.name }}</a></li> |
||||||
|
{% endfor %} |
||||||
|
</ul> |
||||||
|
</td> |
||||||
|
|
||||||
|
<th> </th> |
||||||
|
</tr> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr/> |
||||||
|
{% endwith %} |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
<div class="i-services country_content"> |
||||||
|
<div class="i-descr"> |
||||||
|
<h4>Коротко о наших преимуществах:</h4> |
||||||
|
<ul class="content_list"> |
||||||
|
<li>Эффективная цена</li> |
||||||
|
<li>Опыт и профессионализм специалистов</li> |
||||||
|
<li>Знание разных менталитетов и психологических аспектов проведения переговоров с зарубежными бизнесменами</li> |
||||||
|
<li>Ориентированность в мировых выставочных комплексах </li> |
||||||
|
<li>Гарантии, отчетность по договору, прозрачные безналичные расчеты в России</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="rq-btn-wrap rq-btn-to-hide"> |
||||||
|
|
||||||
|
<div class="rqb-cols"> |
||||||
|
<div class="rqb-button"> |
||||||
|
<div class="rq-order-button"> |
||||||
|
<div class="rqob-wrap"> |
||||||
|
<div class="rqob-price">от 80 € / день</div> |
||||||
|
<div class="rqob-button"> |
||||||
|
<a class="ob-text" href="#">заказать услугу</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
<hr> |
||||||
|
|
||||||
|
<div class="i-staff"> |
||||||
|
<div class="sect-title"><a href="/translators/country/{{ object.url }}/all/">Наши специалисты</a></div> |
||||||
|
|
||||||
|
<div class="i-staff-list"> |
||||||
|
|
||||||
|
<ul> |
||||||
|
{% for user in object_list %} |
||||||
|
<li> |
||||||
|
<a href="{{ user.get_translator_url }}"> |
||||||
|
<div class="sl-item clearfix"> |
||||||
|
<div class="sl-pict">{% include 'client/includes/show_logo.html' with obj=user %}</div> |
||||||
|
<div class="sl-info"> |
||||||
|
<div class="sl-info-wrap"> |
||||||
|
<div class="sl-name">{{ user.get_full_name }}</div> |
||||||
|
<div class="sl-position">{{ user.translator.languages }}</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
{% endfor %} |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<a class="button more" href="/translators/country/{{ object.url }}/all/">Все переводчики</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,59 @@ |
|||||||
|
{% extends 'base_catalog.html' %} |
||||||
|
{% load static %} |
||||||
|
{% load i18n %} |
||||||
|
{% load thumbnail %} |
||||||
|
{% load template_filters %} |
||||||
|
|
||||||
|
|
||||||
|
{% block bread_scrumbs %} |
||||||
|
<div class="bread-crumbs"> |
||||||
|
<a href="/">{% trans 'Главная страница' %}</a> |
||||||
|
{% if object.profile.country %} |
||||||
|
<a href="/translators/country/{{ object.profile.country.url }}/">{{ object.profile.country.name }}</a> |
||||||
|
{% if object.profile.city %} |
||||||
|
<a href="/translators/city/{{ object.profile.city.url }}/">{{ object.profile.city.name }}</a> |
||||||
|
{% endif %} |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
<strong>{{ obect.get_full_name }}</strong> |
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block content_list %} |
||||||
|
<div class="m-article cl-news blog_block"> |
||||||
|
<div class="profile_top"> |
||||||
|
<div class="profile_top_pic"> |
||||||
|
{% if object.profile.avatar %} |
||||||
|
{% thumbnail object.profile.avatar "100x100" format="PNG" as im %} |
||||||
|
<img class="user-avatar" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"/> |
||||||
|
{% endthumbnail %} |
||||||
|
{% else %} |
||||||
|
<img class="user-avatar" src="{% static 'client/img/no-userpic-big.gif' %}" width="100" height="100"/> |
||||||
|
{% endif %} |
||||||
|
</div> |
||||||
|
<div class="profile_top_left_1"> |
||||||
|
<h1>{{ object.get_full_name }}</h1> |
||||||
|
<p><span class="icon1"></span><b>{{ object.translator.languages }}</b></p> |
||||||
|
|
||||||
|
<p>{% ifequal object.translator.gender 'female' %}<span class="icon2"></span>{% endifequal %}{{ object.translator.birth|how_many_years }} лет{% if object.translator.car %}<span class="icon3"></span>Есть личный автомобиль</p>{% endif %} |
||||||
|
</div> |
||||||
|
<div class="profile_top_right_1"> |
||||||
|
{% if object.profile.country %} |
||||||
|
<p><span class="icon4"></span><a href="/translators/country/{{ object.profile.country.url }}/" title="">{{ object.profile.country.name }}</a> |
||||||
|
{% if object.profile.city %}, <a href="/translators/city/{{ object.profile.city.url }}/" title="">{{ object.profile.city.name }}</a>{% endif %}</p> |
||||||
|
{% endif %} |
||||||
|
{% if object.translator.native_language %} |
||||||
|
<p><span class="icon5"></span>{% trans 'Родной язык' %} — {{ object.translator.native_language }}</p> |
||||||
|
{% endif %} |
||||||
|
</div> |
||||||
|
<div class="clear"></div> |
||||||
|
|
||||||
|
<hr> |
||||||
|
{% if object.translator.education %} |
||||||
|
<h3>{% trans 'Образование' %}:</h3> |
||||||
|
{{ object.translator.education }} |
||||||
|
<hr> |
||||||
|
{% endif %} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
{% extends 'base_catalog.html' %} |
||||||
|
{% load i18n %} |
||||||
|
{% load template_filters %} |
||||||
|
|
||||||
|
{% block bread_scrumbs %} |
||||||
|
<div class="bread-crumbs"> |
||||||
|
<a href="/">Главная страница</a> |
||||||
|
<strong>{{ catalog_name }}</strong> |
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block page_title %} |
||||||
|
|
||||||
|
{% endblock %} |
||||||
|
|
||||||
|
{% block content_list %} |
||||||
|
{% with objects=object_list %} |
||||||
|
{% for obj in objects %} |
||||||
|
{% set cur_word = obj.name %} |
||||||
|
{% if cur_word|slice:":1"|lower != prev_word|slice:":1"|lower and forloop.counter != 1 %} |
||||||
|
</ul> |
||||||
|
{% endif %} |
||||||
|
{% if cur_word|slice:":1"|lower != prev_word|slice:":1"|lower %} |
||||||
|
<ul class="leter-list"> |
||||||
|
<div class="leter"><font size="5">{{ cur_word|slice:":1"|upper }}</font></div> |
||||||
|
{% endif %} |
||||||
|
<li> |
||||||
|
<a href="/translators{{ obj.catalog }}{{ obj.url }}/">{{ obj.name }} ({{ obj.translators_count }})</a> |
||||||
|
</li> |
||||||
|
{% set prev_word = obj.name %} |
||||||
|
{% endfor %} |
||||||
|
{% endwith %} |
||||||
|
{% endblock %} |
||||||
@ -1,9 +1,19 @@ |
|||||||
{% load static %} |
{% load static %} |
||||||
{% load template_filters %} |
{% load template_filters %} |
||||||
|
|
||||||
<div class="abn"> |
<div class="abn"> |
||||||
{% if False|fourth %} |
{% with r=False|random4 %} |
||||||
<a target="_blank" href="/redirect/redirect/21/"><img src="{% static 'client/img/partners/unnamed.gif' %}" alt="" /></a> |
{% ifequal r 0 %} |
||||||
{% else %} |
<a target="_blank" href="/redirect/redirect/57/"><img src="{% static 'client/img/partners/cemat15_900x130_bilet.gif' %}" alt="" /></a> |
||||||
<a target="_blank" href="/redirect/redirect/23/"><img src="{% static 'client/img/partners/unnamed_1.gif' %}" alt="" /></a> |
{% endifequal %} |
||||||
{% endif %} |
{% ifequal r 1 %} |
||||||
|
<a target="_blank" href="/redirect/redirect/58/"><img src="{% static 'client/img/partners/beach.png' %}" alt="" /></a> |
||||||
|
{% endifequal %} |
||||||
|
{% ifequal r 2 %} |
||||||
|
<a target="_blank" href="/redirect/redirect/59/"><img src="{% static 'client/img/partners/mims15_900x130_bilet.gif' %}" alt="" /></a> |
||||||
|
{% endifequal %} |
||||||
|
{% ifequal r 3 %} |
||||||
|
<a target="_blank" href="/redirect/redirect/61/"><img src="{% static 'client/img/partners/IPSA_2015_web_900x130.gif' %}" alt="" /></a> |
||||||
|
{% endifequal %} |
||||||
|
{% endwith %} |
||||||
</div> |
</div> |
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue