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