Banners. start

remotes/origin/1203
Kotiuk Nazarii 11 years ago
parent 50beeb8ded
commit 9c47521052
  1. 0
      expobanner/__init__.py
  2. 21
      expobanner/managers.py
  3. 170
      expobanner/models.py
  4. 159
      expobanner/static/banners/css/slider.css
  5. 10
      expobanner/static/banners/js/log.js
  6. 71
      expobanner/static/banners/js/slider.js
  7. 55
      expobanner/templates/banner.html
  8. 32
      expobanner/templates/grid.html
  9. 30
      expobanner/templates/group.html
  10. 74
      expobanner/templates/slider.html
  11. 0
      expobanner/templatetags/__init__.py
  12. 74
      expobanner/templatetags/banner.py
  13. 16
      expobanner/tests.py
  14. 8
      expobanner/urls.py
  15. 14
      expobanner/views.py
  16. 1
      proj/settings.py
  17. 14
      templates/client/blank.html
  18. 7
      templates/client/static_client/js/expo_b.js

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*
from random import choice, shuffle
from django.db import models
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

@ -0,0 +1,170 @@
import hashlib
from datetime import datetime
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
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)
sites = models.ManyToManyField(Site, related_name='site_urls', verbose_name=_('Sites'), null=True, blank=True)
public = models.BooleanField(verbose_name=_('Public'), 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')
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)
public = models.BooleanField(verbose_name=_('Public'), 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 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')
class Banner(models.Model):
objects = BiasedManager()
title = models.CharField(verbose_name=_('Title'), 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)
sort = models.PositiveSmallIntegerField(verbose_name=_('Sort'), default=500)
group = models.ForeignKey(BannerGroup, related_name='banners', verbose_name=_('Group'))
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=_('Is HTML?'), default=False)
flash = models.BooleanField(verbose_name=_('Is Flash?'), default=False)
public = models.BooleanField(verbose_name=_('Public'), 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 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)

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

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

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

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

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

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

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

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

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

@ -0,0 +1,8 @@
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'),
]

@ -0,0 +1,14 @@
from django.shortcuts import redirect, get_object_or_404
from .models import Banner
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)

@ -282,6 +282,7 @@ INSTALLED_APPS = (
'core',
'country',
'directories',
'expobanner',
'exposition',
'file',
'news',

@ -108,6 +108,20 @@ This template include basic anf main styles and js files,
ga('create', 'UA-3151423-1', 'auto');
ga('send', 'pageview');
</script>
<!--test expo_b -->
<script>
$(function () {
var sendData = {
"url": "{{ request.path }}",
"theme": "{{ theme.id }}",
"country": "{{ country.id }}",
"city": "{{ city.id }}",
"tag": "{{ tag.id }}"
}
console.log(sendData);
});
</script>
</head>
<body {% block body_class %}{% endblock %}>

@ -0,0 +1,7 @@
/**
* Created by kotzilla on 17/07/15.
*/
$(function () {
console.log('banners');
});
Loading…
Cancel
Save