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

# -*- 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 # всего кликов
)