You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
4.8 KiB
130 lines
4.8 KiB
# -*- coding: utf-8 -*-
|
|
import os
|
|
import time
|
|
import datetime
|
|
|
|
from django.db import models
|
|
from django.db.models import F
|
|
from django.conf import settings
|
|
from django.core.urlresolvers import reverse
|
|
|
|
|
|
# куда сохранять загруженные изображения
|
|
UPLOAD_DIR = getattr(settings, 'BANNERS_DIR', 'banners/')
|
|
|
|
|
|
def pic_upload_to(instance, filename):
|
|
"""Куда и под каким именем сохранять баннеры."""
|
|
path = UPLOAD_DIR
|
|
slot_id = u'%s' % instance.slot.pk
|
|
ext = os.path.splitext(os.path.basename(filename))[1]
|
|
filename = u'%s%s' % (int(time.time()), ext) # use timestamp as filename
|
|
return os.path.join(path, slot_id, filename)
|
|
|
|
|
|
class SlotManager(models.Manager):
|
|
def next_banner(self, reverse_id):
|
|
"""Возвращает баннер (из числа опубликованных), который не показывали
|
|
дольше всего.
|
|
Счётчик показов не увеличивает!, т.к. показ засчитываем только если к
|
|
баннеру обратились из браузера клиента.
|
|
"""
|
|
try:
|
|
slot = self.filter(reverse_id=reverse_id)[0]
|
|
obj = (slot.banners.filter(published=True)
|
|
.order_by('last_viewed_at')[0])
|
|
return obj
|
|
except IndexError:
|
|
return None
|
|
|
|
|
|
class Slot(models.Model):
|
|
"""Блок (группа) баннеров."""
|
|
name = models.CharField(u'название', max_length=100, db_index=True,
|
|
unique=True)
|
|
reverse_id = models.SlugField(u'id', max_length=40, db_index=True,
|
|
unique=True, help_text=(u'Уникальный идентификатор, '
|
|
u'который используется для связи с данным блоком.'))
|
|
|
|
created_at = models.DateTimeField(u'создан', auto_now_add=True)
|
|
updated_at = models.DateTimeField(u'изменен', auto_now=True)
|
|
|
|
objects = SlotManager()
|
|
|
|
class Meta:
|
|
verbose_name = u'блок баннеров'
|
|
verbose_name_plural = u'блоки баннеров'
|
|
ordering = ['name',]
|
|
|
|
def __unicode__(self):
|
|
return u'%s' % self.name
|
|
|
|
def save(self, *args, **kwargs):
|
|
self.name = self.name.strip()
|
|
super(Slot, self).save(*args, **kwargs)
|
|
|
|
|
|
class Banner(models.Model):
|
|
"""Баннеры."""
|
|
slot = models.ForeignKey(Slot, related_name=u'banners')
|
|
|
|
pic = models.ImageField(u'изображение', upload_to=pic_upload_to)
|
|
dest_url = models.URLField(u'URL перехода')
|
|
title = models.CharField(u'название', max_length=100, db_index=True)
|
|
|
|
published = models.BooleanField(u'опубликован?', default=False)
|
|
|
|
views_count = models.PositiveIntegerField(u'показов', default=0)
|
|
last_viewed_at = models.DateTimeField(u'последний показ',
|
|
default=datetime.datetime(1970, 1, 1), editable=False)
|
|
clicks_count = models.PositiveIntegerField(u'кликов', default=0)
|
|
|
|
created_at = models.DateTimeField(u'создан', auto_now_add=True)
|
|
updated_at = models.DateTimeField(u'изменен', auto_now=True)
|
|
|
|
class Meta:
|
|
verbose_name = u'баннер'
|
|
verbose_name_plural = u'баннеры'
|
|
ordering = ['created_at',]
|
|
|
|
def __unicode__(self):
|
|
return u'%s' % self.dest_url
|
|
|
|
#@models.permalink
|
|
def get_absolute_url(self):
|
|
"""Возвращает урл превью - для админки."""
|
|
return reverse('banners-preview', kwargs={'id': self.pk,})
|
|
|
|
#@models.permalink
|
|
def get_show_url(self):
|
|
"""Возвращает урл показа баннера - для шаблонов."""
|
|
return reverse('banners-show', kwargs={'id': self.pk,})
|
|
|
|
#@models.permalink
|
|
def get_click_url(self):
|
|
"""Возвращает урл перехода по клику - для шаблонов."""
|
|
return reverse('banners-click', kwargs={'id': self.pk,})
|
|
|
|
def ctr(self):
|
|
"""Показатель кликабельности."""
|
|
if self.views_count > 0:
|
|
ctr = float(self.clicks_count) / self.views_count * 100
|
|
return u'%.1f%%' % ctr
|
|
else:
|
|
return u'-'
|
|
ctr.short_description = u'CTR'
|
|
|
|
|
|
def update_views(id):
|
|
"""Обновляет статистику показов по id."""
|
|
return Banner.objects.filter(pk=id).update(
|
|
views_count = F('views_count') + 1, # всего показов
|
|
last_viewed_at = datetime.datetime.now() # дата последнего показа
|
|
)
|
|
|
|
|
|
def update_clicks(id):
|
|
"""Обновляет статистику кликов по id."""
|
|
return Banner.objects.filter(pk=id).update(
|
|
clicks_count = F('clicks_count') + 1 # всего кликов
|
|
)
|
|
|