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.
 
 
 
 
 
 

402 lines
16 KiB

# -*- coding: utf-8 -*-
import hashlib
import random
from collections import namedtuple
from datetime import date, datetime
from conference.models import Conference
from country.models import Country
from django.conf import settings
from django.contrib.sites.models import Site
from django.db import models
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _
from exposition.models import Exposition
from functions.custom_fields import MonthMultiSelectField
from theme.models import Theme
from .managers import BannerGroupCached, BiasedManager, TopCached, URLCached
from .mixins import StatMixin
class URL(models.Model):
"""
Model for urls or regex urls that can be used in banners representation
"""
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)
objects = models.Manager()
cached = URLCached()
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):
"""
place where banner can be show
"""
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)
objects = models.Manager()
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 Customer(models.Model):
name = models.CharField(_(u'Название'), max_length=255)
description = models.TextField(_(u'Дополнительная информация'), blank=True, null=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 u'{name}'.format(name=self.name)
class Meta:
ordering = ['name']
verbose_name = _(u'Заказчик')
verbose_name_plural = _(u'Заказчики')
class Banner(models.Model, StatMixin):
"""
Uses for store information about banners. Also can be used as tracked link
"""
objects = BiasedManager()
customer = models.ForeignKey(Customer, verbose_name=_(u'Заказчик'), null=True, blank=True)
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)
fr = models.DateField(default=date.today())
to = models.DateField(blank=True, null=True)
theme = models.ManyToManyField(Theme, blank=True, null=True, verbose_name=_(u'Тематика'))
country = models.ManyToManyField(Country, blank=True, null=True, verbose_name=_(u'Страна'))
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)],
default=1
)
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)
popup = models.BooleanField(verbose_name=_('Popup?'), default=False)
paid = models.BooleanField(verbose_name=_('Is Paid event link?'), default=False)
link = models.BooleanField(verbose_name=_('Is simple link?'), default=False)
# for detecting popups
cookie = models.CharField(max_length=30, blank=True, null=True, default=settings.DEFAULT_POPUP_COOKIE)
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)
# password for clients
stat_pswd = models.CharField(max_length=16)
class Meta:
ordering = ['-public']
def get_admin_url(self):
return '/admin/expobanners/banners/banner/%d/edit/' % self.id
@property
def key(self):
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, t):
"""
creating log by request
"""
log = {
'type': t,
'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)
def get_click_link(self):
return '/expo-b/click/%d/'%self.id
class Meta:
ordering = ['sort']
verbose_name = _('Banner')
verbose_name_plural = _('Banners')
class Log(models.Model):
"""
store information about showing and clicking of banners
"""
banner = models.ForeignKey(Banner, related_name='banner_logs')
group = models.ForeignKey(BannerGroup, related_name='group_logs', verbose_name=_('Group'), blank=True, null=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):
"""
store aggregated data of logs
"""
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, null=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'), null=True, default=0)
click = models.PositiveIntegerField(verbose_name=_('Clicks'), null=True, default=0)
unique_click = models.PositiveIntegerField(verbose_name=_('Unique Views'), blank=True, null=True, default=0)
unique_view = models.PositiveIntegerField(verbose_name=_('Unique Clicks'), null=True, default=0)
updated_at = models.DateTimeField(auto_now=True, null=True)
def __unicode__(self):
return '%s - (%s)' % (self.banner, self.date)
class Meta:
ordering = ['-date']
class Paid(models.Model, StatMixin):
"""
store information about paid events
"""
expo = 1
conf = 2
kind = models.PositiveSmallIntegerField(verbose_name=_(u'Тип'), default=1, db_index=True)
tickets = models.ForeignKey(Banner, related_name='paid_tickets')
participation = models.ForeignKey(Banner, related_name='paid_participation', null=True)
official = models.ForeignKey(Banner, related_name='paid_official')
catalog = models.ForeignKey(Banner, related_name='paid_catalog')
logo = models.ImageField(upload_to='expo-b/paid', blank=True)
organiser = models.CharField(max_length=100, blank=True)
public = models.BooleanField(default=True, verbose_name=_(u'Активная'))
stat_pswd = models.CharField(max_length=16)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-public']
def get_event(self):
model = Exposition if self.kind == self.expo else Conference
try:
return model.objects.get(paid_new_id=self.pk)
except model.DoesNotExist:
return None
class PaidStat(models.Model):
"""
aggregated data of paid logs
"""
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)
tickets_clicks = models.PositiveIntegerField(default=0)
participation_clicks = models.PositiveIntegerField(default=0)
official_clicks = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['-date']
class Top(models.Model, StatMixin):
"""
store information about events in top
"""
YEARS = map(
lambda x: (x, x),
tuple(xrange(date.today().year - 1, date.today().year + 5))
)
link = models.ForeignKey(Banner)
catalog = models.CharField(max_length=16, verbose_name=_(u'Каталог для топа'))
position = models.PositiveIntegerField(blank=True, default=2, null=True, verbose_name=_(u'Позиция'))
theme = models.ManyToManyField('theme.Theme', blank=True, null=True, verbose_name=_(u'Тематики'))
excluded_tags = models.ManyToManyField('theme.Tag', blank=True, null=True, verbose_name=_(u'Исключить теги'))
country = models.ManyToManyField('country.Country', blank=True, null=True, verbose_name=_(u'Страны'))
cities = models.ManyToManyField('city.City', related_name='top_in_set', blank=True, null=True, verbose_name=_(u'Города'))
months = MonthMultiSelectField(_(u'Топ месяца'), blank=True, null=True, default=None, max_length=255,)
years = models.PositiveSmallIntegerField(_(u'Топ года'), choices=YEARS, blank=True, null=True, default=None)
excluded_cities = models.ManyToManyField('city.City', blank=True, null=True, verbose_name=_(u'Исключить города'))
fr = models.DateField(default=date.today(), verbose_name=_(u'Начало'))
to = models.DateField(blank=True, null=True, verbose_name=_(u'Конец'))
stat_pswd = models.CharField(max_length=16)
objects = models.Manager()
cached = TopCached()
class Meta:
ordering = ['position']
def get_event(self):
try:
return self.exposition_set.all()[0]
except IndexError:
return None
class TopStat(models.Model):
"""
aggregated data of logs events in top
"""
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)
class MainPage(models.Model, StatMixin):
"""
events on main page info
"""
link = models.ForeignKey(Banner)
position = models.PositiveIntegerField(blank=True, default=2, null=True, verbose_name=_(u'Позиция'))
public = models.BooleanField(default=True, verbose_name=_(u'Активная'))
stat_pswd = models.CharField(max_length=16)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-public']
def get_event(self):
try:
return self.exposition_set.all()[0]
except IndexError:
try:
return self.conference_set.all()[0]
except IndexError:
return None
def __unicode__(self):
return self.get_event().url
def generatePassword(length=5):
"""
generate random password
"""
SYMBOLS = [',', '.', '?', '!', '-', '+', '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A',
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '#']
PASSWORD_LENGTH = length
newPassword = []
for i in range(PASSWORD_LENGTH):
newPassword.append(SYMBOLS[random.randrange(0, len(SYMBOLS))])
return ''.join(newPassword)
def generate_stat_pass(sender, **kwargs):
obj = kwargs['instance']
if not obj.stat_pswd:
obj.stat_pswd = generatePassword()
obj.save()
post_save.connect(generate_stat_pass, sender=Banner)
post_save.connect(generate_stat_pass, sender=Paid)
post_save.connect(generate_stat_pass, sender=Top)