Skip to content

Instantly share code, notes, and snippets.

@razum2um
Created May 21, 2011 03:21
Show Gist options
  • Save razum2um/984201 to your computer and use it in GitHub Desktop.
Save razum2um/984201 to your computer and use it in GitHub Desktop.
zavode banners#2
diff --git a/cms/admin.py b/cms/admin.py
index 7e84d77..8438b67 100644
--- a/cms/admin.py
+++ b/cms/admin.py
@@ -9,6 +9,7 @@ from cms.models import *
from cms.forms import MenuItemAdminForm, BlockAdminForm
from cms.forms import NewsAdminForm, ArticleAdminForm
from cms.forms import GalleryAdminForm, ImageAdminForm
+from cms.forms import BannerAdminForm
# Utils
from django.core.urlresolvers import reverse
from django.conf.urls.defaults import patterns
@@ -220,6 +221,9 @@ class ImageAdmin(admin.ModelAdmin):
list_display = ('admin_thumb', 'gallery', 'title')
list_filter = ('gallery',)
+class BannerAdmin(admin.ModelAdmin):
+ form = BannerAdminForm
+
if "gallery" in getattr(settings, 'CMS_ENABLED_TYPES', []):
admin.site.register(Gallery, GalleryAdmin)
cms.settings.CMS_ADMIN_MATERIALS.append('cms.models.Gallery')
@@ -229,5 +233,5 @@ if "gallery" in getattr(settings, 'CMS_ENABLED_TYPES', []):
if "Banner" not in getattr(settings, 'CMS_EXCLUDE_BLOCKS', ["Banner"]):
cms.settings.CMS_ADMIN_STRUCTURE.append('cms.models.Banner')
- admin.site.register(Banner)
+ admin.site.register(Banner, BannerAdmin)
diff --git a/cms/blocks/Banner/views.py b/cms/blocks/Banner/views.py
index ad916ac..bfd4989 100644
--- a/cms/blocks/Banner/views.py
+++ b/cms/blocks/Banner/views.py
@@ -32,19 +32,26 @@ def default(request, block):
hours_regexp[hour] = '1'
hours_regexp = ''.join(hours_regexp)
- blocks = Banner.objects.all()
- blocks = blocks.filter(Q(num_shows_left=None)|Q(num_shows_left__gt=0))
- blocks = blocks.filter(start_dt__lte=now.date()).filter(stop_dt__gte=now.date())
+ banners = block.banner_set.all()
+ banners = banners.filter(Q(num_shows_left=None)|Q(num_shows_left__gt=0))
+ banners = banners.filter(start_dt__lte=now.date()).filter(stop_dt__gte=now.date())
# no regex in sqlite?
- blocks = blocks.filter(mode_hours__regex=hours_regexp).filter(mode_weekday__regex=weekday_regexp)
- blocks = blocks.order_by('?')
- block = blocks[0] # db-hit here
- if block.num_shows_left:
- block.num_shows_left -= 1
+ banners = banners.filter(mode_hours__regex=hours_regexp).filter(mode_weekday__regex=weekday_regexp)
+ banners = banners.order_by('?')
+ if not banners.count():
+ return u''
+ banner = banners[0] # db-hit here
+ if banner.num_shows_left:
+ banner.num_shows_left -= 1
# TODO: wtf?? forced saving needed,
# otherwise got no '/banners/' into path
- block.save()
- resp = block.html
+ banner.save()
+
+ # wrap it into leave link if any
+ if banner.link:
+ resp = '<a href="%s">%s</a>' % (banner.get_leave_link(), banner.html)
+ else:
+ resp = banner.html
return mark_safe(resp)
@render_to('admin/cms/block_config.html')
diff --git a/cms/fields.py b/cms/fields.py
index 4f0c599..e86d90f 100644
--- a/cms/fields.py
+++ b/cms/fields.py
@@ -264,6 +264,53 @@ class PlainWidget(forms.HiddenInput):
output.append(u" <a href=\"%s\">Редактировать</a>" % url )
return mark_safe(u''.join(output))
+class BitWiseArrayWidget(forms.CheckboxSelectMultiple):
+ def render(self, name, value, attrs=None, choices=()):
+ if value:
+ # it's None by creating
+ values = [ int(x) for x in value if x ]
+ global_index = lambda lst, test: [idx for idx, val in enumerate(lst) if val==test ]
+ value = global_index(values, 1) # picks indexes of items where val=1
+
+ return super(BitWiseArrayWidget, self).render(name, value, attrs, choices)
+
+class BitWiseArrayFormField(forms.MultipleChoiceField):
+ def __init__(self, *args, **kwargs):
+ super(BitWiseArrayFormField, self).__init__(*args, **kwargs)
+ self.choices = self.get_choices()
+
+ def get_choices(self):
+ raise NotImplementedError()
+
+ def to_python(self, value):
+ '''
+ value contains indexes of picked elems
+ '''
+ ret = ['0']*len(self.choices) # reset bit-wise array
+ if not len(value):
+ return ''.join(ret)
+ for v in value:
+ ret[int(v)] = '1'
+ return ''.join(ret)
+
+class HourBitWiseArrayFormField(BitWiseArrayFormField):
+ def get_choices(self):
+ choices = []
+ for i in range(24):
+ choices.append((i, '%02d:00' % i + '-%02d:59' %i))
+ return choices
+
+class WeekBitWiseArrayFormField(BitWiseArrayFormField):
+ def get_choices(self):
+ return [
+ (0,_('Monday')),
+ (1,_('Tuesday')),
+ (2,_('Wednesday')),
+ (3,_('Thursday')),
+ (4,_('Friday')),
+ (5,_('Saturday')),
+ (6,_('Sunday')),
+ ]
if south:
add_introspection_rules([], ["^cms\.fields\.PickledObjectField"])
diff --git a/cms/forms.py b/cms/forms.py
index 0abc599..73f0db8 100644
--- a/cms/forms.py
+++ b/cms/forms.py
@@ -5,7 +5,8 @@ from django.db.models import Q
from django import forms
from mptt.forms import TreeNodeChoiceField, TreeNodeMultipleChoiceField
# Widgets
-from cms.fields import ThumbImageWidget, PlainWidget
+from cms.fields import HourBitWiseArrayFormField, WeekBitWiseArrayFormField
+from cms.fields import ThumbImageWidget, PlainWidget, BitWiseArrayWidget
from uploadify.widgets import UploadifyAdminWidget
# i18n
from django.utils.translation import ugettext_lazy as _
@@ -213,3 +214,9 @@ class GalleryAdminForm(forms.ModelForm):
tasks.gallery_add_zip(self.instance, path)
return self.instance
+class BannerAdminForm(forms.ModelForm):
+ mode_hours = HourBitWiseArrayFormField(widget=BitWiseArrayWidget)
+ mode_weekday = WeekBitWiseArrayFormField(widget=BitWiseArrayWidget())
+ class Meta:
+ model = Banner
+
diff --git a/cms/migrations/0024_auto__add_field_banner_block.py b/cms/migrations/0024_auto__add_field_banner_block.py
new file mode 100644
index 0000000..6adf353
--- /dev/null
+++ b/cms/migrations/0024_auto__add_field_banner_block.py
@@ -0,0 +1,148 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding field 'Banner.block'
+ db.add_column('cms_banner', 'block', self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['cms.Block']), keep_default=False)
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'Banner.block'
+ db.delete_column('cms_banner', 'block_id')
+
+
+ models = {
+ 'cms.article': {
+ 'Meta': {'object_name': 'Article'},
+ 'body': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image': ('cms.fields.RemovableImageField', [], {'max_length': '100', 'blank': 'True'}),
+ 'list_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'cms_article_type'", 'to': "orm['cms.ListType']"}),
+ 'menu_items': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'cms_article_items'", 'symmetrical': 'False', 'to': "orm['cms.MenuItem']"}),
+ 'publish': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'short': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '250', 'blank': 'True'}),
+ 'template': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '250'})
+ },
+ 'cms.banner': {
+ 'Meta': {'object_name': 'Banner'},
+ 'alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'banner': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'block': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Block']"}),
+ 'html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'link': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'mode_hours': ('django.db.models.fields.CharField', [], {'default': "'111111111111111111111111'", 'max_length': '24'}),
+ 'mode_weekday': ('django.db.models.fields.CharField', [], {'default': "'1111111'", 'max_length': '7'}),
+ 'num_shows_left': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'referals': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}),
+ 'start_dt': ('django.db.models.fields.DateField', [], {}),
+ 'stop_dt': ('django.db.models.fields.DateField', [], {})
+ },
+ 'cms.block': {
+ 'Meta': {'object_name': 'Block'},
+ 'data': ('cms.fields.PickledObjectField', [], {'default': "''", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'region': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'view': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '250', 'null': 'True', 'blank': 'True'}),
+ 'visible_on': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'blocks'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['cms.MenuItem']"}),
+ 'weight': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'cms.gallery': {
+ 'Meta': {'object_name': 'Gallery'},
+ 'body': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image': ('cms.fields.RemovableImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['cms.Gallery']"}),
+ 'publish': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '250', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+ },
+ 'cms.image': {
+ 'Meta': {'object_name': 'Image'},
+ 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'images'", 'to': "orm['cms.Gallery']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+ 'title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '250', 'blank': 'True'})
+ },
+ 'cms.link': {
+ 'Meta': {'object_name': 'Link'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'redirect': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'url': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ 'cms.listtype': {
+ 'Meta': {'object_name': 'ListType'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '250', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '250'})
+ },
+ 'cms.menuitem': {
+ 'Meta': {'object_name': 'MenuItem'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
+ 'full_url': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['cms.MenuItem']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '250', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+ },
+ 'cms.news': {
+ 'Meta': {'object_name': 'News'},
+ 'body': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'date': ('django.db.models.fields.DateTimeField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image': ('cms.fields.RemovableImageField', [], {'max_length': '100', 'blank': 'True'}),
+ 'list_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'cms_news_type'", 'to': "orm['cms.ListType']"}),
+ 'menu_items': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'cms_news_items'", 'symmetrical': 'False', 'to': "orm['cms.MenuItem']"}),
+ 'publish': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'short': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '250', 'blank': 'True'}),
+ 'template': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '250'})
+ },
+ 'cms.page': {
+ 'Meta': {'object_name': 'Page'},
+ 'body': ('django.db.models.fields.TextField', [], {}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image': ('cms.fields.RemovableImageField', [], {'max_length': '100', 'blank': 'True'}),
+ 'publish': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'short': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '250', 'blank': 'True'}),
+ 'template': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '250'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ }
+ }
+
+ complete_apps = ['cms']
diff --git a/cms/models.py b/cms/models.py
index e50bd02..4edf86e 100644
--- a/cms/models.py
+++ b/cms/models.py
@@ -6,6 +6,7 @@ import re
# Main Imports
from django.db import models
from django.db.models.base import ModelBase
+from django.utils.http import urlquote
from mptt.models import MPTTModel
from django.contrib.contenttypes import generic
from django.core.exceptions import ValidationError
@@ -570,6 +571,7 @@ class Banner(models.Model):
link = models.CharField(max_length=255,
null=True, blank=True,
help_text=_('If no link given -> no link in output'))
+ block = models.ForeignKey('Block', help_text=_('concret block'))
def __unicode__(self):
if self.banner:
@@ -578,9 +580,15 @@ class Banner(models.Model):
basename = self.alt_text
return basename
- def save(self, *args, **kwargs):
+ def clean(self):
+ # Don't allow draft empty banner&html.
if not self.banner and not self.html:
- raise Exception('Provide eiher `html` or `file`')
+ raise ValidationError(_('Provide eiher `html` or `file`'))
+ basename = os.path.basename(self.banner.name)
+ if self.banner and not RE_FLASH_FMT.search(basename) and not RE_IMAGE_FMT.search(basename):
+ raise ValidationError(_('Unknown file format'))
+
+ def save(self, *args, **kwargs):
if self.banner:
basename = os.path.basename(self.banner.name)
if RE_IMAGE_FMT.search(basename):
@@ -592,18 +600,12 @@ class Banner(models.Model):
<embed src="%s" width="550" height="400">
</embed>
</object>''' % (basename, self.banner.url)
- else:
- raise Exception('Unknown file format')
- if self.link:
- self.html = '<a href="%s">%s</a>' % (self.link, self.html)
-
- # hanlde some input errors
- if len(self.mode_weekday)!=7:
- mode_weekday = self.mode_weekday[:7]
- mode_weekday.extend((7-len(mode_weekday))*['1'])
- self.mode_weekday = mode_weekday
- if len(self.mode_hours)!=24:
- mode_hours = self.mode_hours[:24]
- mode_hours.extend((24-len(mode_hours))*['1'])
- self.mode_hours = mode_hours
+ # build url at runtime throgh /leave?ref=&banner_id=
+ # if self.link:
+ # self.html = '<a href="%s">%s</a>' % (self.link, self.html)
+
super(Banner, self).save(*args, **kwargs)
+
+ def get_leave_link(self):
+ if self.link:
+ return reverse('cms.views.leave') + '?banner_id=' + str(self.id) + '&ref=' + urlquote(self.link)
diff --git a/cms/urls.py b/cms/urls.py
index 585c3c3..e3a3eb3 100644
--- a/cms/urls.py
+++ b/cms/urls.py
@@ -31,6 +31,7 @@ urlpatterns += patterns('cms.views',
url(r'^image/(?P<id>\d+)/$', 'image_by_id', name='image_by_id'),
url(r'^mailto/$', 'mailto', name='mailto'),
url(r'^sitemap/$', 'sitemap', name='sitemap'),
+ url(r'^leave/$', 'leave', name='leave'), # banners refaral counter
# Admin url
url(r'^cms/list/choices/(?P<id>\d+)/', 'get_menu_items_choices', name='get_menu_items_choices'),
url(r'^cms/objects/choices/(?P<id>\d+)/', 'get_objects_choices', name='get_objects_choices'),
diff --git a/cms/views.py b/cms/views.py
index 2dd47e8..64f138e 100644
--- a/cms/views.py
+++ b/cms/views.py
@@ -265,6 +265,18 @@ def mailto(request, form_class=None, template="cms/mailto.html", title=_('Feedba
return output
+def leave(request):
+ referal = request.GET.get('ref')
+ banner_id = request.GET.get('banner_id')
+ if referal and banner_id:
+ # exiting by banner click
+ banner = get_object_or_404(Banner, id=banner_id)
+ banner.referals += 1
+ banner.save()
+ return HttpResponseRedirect(referal)
+ raise Http404()
+
+
################################################################
### SiteMap ###
################################################################
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment