Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 09d2896
Showing
18 changed files
with
372 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.pyc | ||
*.egg-info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Copyright (c) 2013, FEINHEIT GmbH and individual contributors. | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without modification, | ||
are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
|
||
2. Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
|
||
3. Neither the name of FEINHEIT GmbH nor the names of its contributors | ||
may be used to endorse or promote products derived from this software | ||
without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
include LICENSE | ||
include MANIFEST.in | ||
include README.rst | ||
include requirements.txt | ||
include setuplib.py | ||
recursive-include feincms_banners/static * | ||
recursive-include feincms_banners/locale * | ||
recursive-include feincms_banners/templates * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
=========================================================================== | ||
feincms-banners -- a simple banner system with views and clicks for FeinCMS | ||
=========================================================================== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
VERSION = (1, 0, 0) | ||
__version__ = '.'.join(map(str, VERSION)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from django.contrib import admin | ||
|
||
from feincms_banners import models | ||
|
||
|
||
admin.site.register(models.Banner, | ||
list_display=('name', 'is_active', 'type', 'url', 'active_from', | ||
'active_until', 'embeds', 'impressions', 'click_count'), | ||
list_filter=('is_active', 'type'), | ||
raw_id_fields=('mediafile',), | ||
search_fields=('name', 'url', 'code'), | ||
) | ||
admin.site.register(models.Click, | ||
list_display=('timestamp', 'banner', 'ip', 'user_agent', 'referrer'), | ||
search_fields=('banner__name', 'user_agent', 'referrer'), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from django.db import models | ||
from django.template.loader import render_to_string | ||
from django.utils.translation import ugettext_lazy as _ | ||
|
||
from feincms_banners.models import Banner | ||
|
||
from feincms.admin.item_editor import FeinCMSInline | ||
|
||
|
||
class BannerContentInline(FeinCMSInline): | ||
raw_id_fields = ('specific',) | ||
|
||
|
||
class BannerContent(models.Model): | ||
feincms_item_editor_inline = BannerContentInline | ||
|
||
is_section_aware = True | ||
|
||
specific = models.ForeignKey(Banner, verbose_name=_('specific'), | ||
blank=True, null=True, help_text=_('If you leave this empty, a random banner will be selected.'), | ||
limit_choices_to={'is_active': True}) | ||
type = models.CharField(_('type'), max_length=20, choices=Banner.TYPE_CHOICES) | ||
|
||
class Meta: | ||
abstract = True | ||
verbose_name = _('banner') | ||
verbose_name = _('banners') | ||
|
||
def render(self, **kwargs): | ||
if self.specific: | ||
if self.specific.is_active: | ||
banner = self.specific | ||
type = banner.type | ||
else: | ||
return u'' | ||
else: | ||
try: | ||
banner = Banner.objects.active().filter( | ||
type=self.type).select_related('mediafile').order_by('?')[0] | ||
type = self.type | ||
except IndexError: | ||
return u'' | ||
|
||
return render_to_string([ | ||
'content/banner/%s.html' % type, | ||
'content/banner/default.html', | ||
], {'content': self, 'banner': banner}) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
from random import choice | ||
|
||
from django.db import models | ||
from django.db.models import Q | ||
from django.utils import timezone | ||
from django.utils.translation import ugettext_lazy as _ | ||
|
||
from feincms.module.medialibrary.fields import MediaFileForeignKey | ||
from feincms.module.medialibrary.models import MediaFile | ||
|
||
|
||
def generate_key(): | ||
return ''.join([ | ||
choice('abcdefghijklmnopqrstuvwxyz0123456789-_') for i in range(40)]) | ||
|
||
|
||
class BannerManager(models.Manager): | ||
def active(self): | ||
return self.filter( | ||
Q(is_active=True, active_from__lte=timezone.now()) | ||
& ( | ||
Q(active_until__isnull=True) | ||
| Q( | ||
active_until__isnull=False, | ||
active_until__gte=timezone.now() | ||
) | ||
) | ||
) | ||
|
||
|
||
class Banner(models.Model): | ||
SKYSCRAPER = 'skyscraper' | ||
LEADERBOARD = 'leaderboard' | ||
BOX = 'box' | ||
|
||
TYPE_CHOICES = ( | ||
(SKYSCRAPER, _('skyscraper')), | ||
(LEADERBOARD, _('leaderboard')), | ||
(BOX, _('box')), | ||
) | ||
|
||
is_active = models.BooleanField(_('is active'), default=True) | ||
name = models.CharField(_('name'), max_length=100, | ||
help_text=_('Only for internal use, will not be shown on the website.' | ||
)) | ||
mediafile = MediaFileForeignKey(MediaFile, verbose_name=_('media file')) | ||
url = models.URLField(_('URL'), verify_exists=False) | ||
type = models.CharField(_('type'), max_length=20, choices=TYPE_CHOICES) | ||
code = models.CharField(_('code'), max_length=40, default=generate_key, | ||
unique=True) | ||
|
||
active_from = models.DateTimeField(_('active from'), default=timezone.now) | ||
active_until = models.DateTimeField(_('active until'), | ||
blank=True, null=True) | ||
|
||
embeds = models.PositiveIntegerField(_('embeds'), default=0, | ||
editable=False, | ||
help_text=_('How many times has this banner been embdedded on a' | ||
' website?') | ||
impressions = models.PositiveIntegerField(_('impressions'), default=0, | ||
editable=False, | ||
help_text=_('How many times has an impression been registered using' | ||
' a Javascript callback, verifying that it actually was a' | ||
' browser? (Too low because of network issues and deactivated' | ||
' Javascript support in some browsers.)')) | ||
|
||
objects = BannerManager() | ||
|
||
class Meta: | ||
ordering= ['-active_from'] | ||
verbose_name = _('banner') | ||
verbose_name_plural = _('banners') | ||
|
||
def __unicode__(self): | ||
return self.name | ||
|
||
@models.permalink | ||
def get_absolute_url(self): | ||
return ('banner_click', (), {'code': self.code}) | ||
|
||
@models.permalink | ||
def impression_url(self): | ||
return ('banner_impression', (), {'code': self.code}) | ||
|
||
def click(self, request): | ||
self.clicks.create( | ||
ip=request.META.get('REMOTE_ADDR'), | ||
user_agent=request.META.get('HTTP_USER_AGENT', ''), | ||
referrer=request.META.get('HTTP_REFERER', ''), | ||
) | ||
|
||
def click_count(self): | ||
return self.clicks.count() | ||
click_count.short_description = _('click count') | ||
|
||
|
||
class Click(models.Model): | ||
banner = models.ForeignKey(Banner, verbose_name=_('banner'), | ||
related_name='clicks') | ||
timestamp = models.DateTimeField(_('timestamp'), default=timezone.now) | ||
ip = models.IPAddressField(_('IP'), blank=True, null=True) | ||
user_agent = models.TextField(_('user agent'), blank=True, default='') | ||
referrer = models.TextField(_('referrer'), blank=True, default='') | ||
|
||
class Meta: | ||
orering = ['-timestamp'] | ||
verbose_name = _('click') | ||
verbose_name_plural = _('clicks') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<a href="{{ banner.get_absolute_url }}" target="_blank"> | ||
<img src="{{ banner.mediafile.file.url }}" alt=""></a> | ||
<script> | ||
(function() { try { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open('GET', '{{ banner.impression_url }}'); | ||
xhr.send(null); | ||
} catch(e) {}; })(); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<!-- banner type unknown --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<div class="content" style="background:none;overflow:hidden;"> | ||
<a href="{{ banner.get_absolute_url }}" target="_blank"> | ||
<img src="{{ banner.mediafile.file.url }}" alt=""> | ||
</a> | ||
</div> | ||
<script> | ||
(function() { try { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open('GET', '{{ banner.impression_url }}'); | ||
xhr.send(null); | ||
} catch(e) {}; })(); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<div style="margin-top:35px;"> | ||
<div style="font-size:10px;position:relative;top:8px;left:1px;">Anzeige</div> | ||
<div class="box" style="background:none;overflow:hidden;padding:8px 0 0 0;margin:0;"> | ||
{% if banner.mediafile.type == 'swf' %} | ||
<object type='application/x-shockwave-flash' data='{{ banner.mediafile.file.url }}' width='160' height='600'> | ||
<param name='allowScriptAccess' value='always' /> | ||
<param name='movie' value='{{ banner.mediafile.file.url }}' /> | ||
</object> | ||
{% else %} | ||
<a href="{{ banner.get_absolute_url }}" target="_blank"> | ||
<img src="{{ banner.mediafile.file.url }}" alt=""> | ||
</a> | ||
{% endif %} | ||
</div> | ||
</div> | ||
<script> | ||
(function() { try { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open('GET', '{{ banner.impression_url }}'); | ||
xhr.send(null); | ||
} catch(e) {}; })(); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from django.conf.urls.defaults import url, patterns, include | ||
|
||
|
||
urlpatterns = patterns('feincms_banners.views', | ||
url(r'^b/c/(?P<code>[^/]+)/$', 'click', name='banner_click'), | ||
url(r'^b/i/(?P<code>[^/]+)/$', 'impression', name='banner_impression'), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from django.db.models import F | ||
from django.http import HttpResponse, HttpResponseRedirect | ||
from django.shortcuts import get_object_or_404 | ||
|
||
from feincms_banners.models import Banner | ||
|
||
|
||
def click(request, code): | ||
banner = get_object_or_404(Banner, code=code) | ||
banner.click(request) | ||
return HttpResponseRedirect(banner.url) | ||
|
||
|
||
def impression(request, code): | ||
if Banner.objects.filter(code=code).update( | ||
impressions=F('impressions') + 1 | ||
): | ||
return HttpResponse('+1') | ||
return HttpResponse('?') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
feincms>=1.6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#!/usr/bin/env python | ||
|
||
from distutils.core import setup | ||
import os | ||
import setuplib | ||
|
||
packages, package_data = setuplib.find_packages('feincms_banners') | ||
|
||
setup(name='feincms-banners', | ||
version=__import__('feincms_banners').__version__, | ||
description='A simple banner system with views and clicks for FeinCMS.', | ||
long_description=open(os.path.join(os.path.dirname(__file__), 'README.rst')).read(), | ||
author='Matthias Kestenholz', | ||
author_email='mk@feinheit.ch', | ||
url='https://github.com/matthiask/feincms-banners/', | ||
license='BSD License', | ||
platforms=['OS Independent'], | ||
packages=packages, | ||
package_data=package_data, | ||
classifiers=[ | ||
'Development Status :: 5 - Production/Stable', | ||
'Environment :: Web Environment', | ||
'Framework :: Django', | ||
'Intended Audience :: Developers', | ||
'License :: OSI Approved :: BSD License', | ||
'Operating System :: OS Independent', | ||
'Programming Language :: Python', | ||
'Topic :: Internet :: WWW/HTTP :: Dynamic Content', | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import os | ||
|
||
|
||
__all__ = ['find_files'] | ||
|
||
|
||
def fullsplit(path, result=None): | ||
""" | ||
Split a pathname into components (the opposite of os.path.join) in a | ||
platform-neutral way. | ||
""" | ||
if result is None: | ||
result = [] | ||
head, tail = os.path.split(path) | ||
if head == '': | ||
return [tail] + result | ||
if head == path: | ||
return result | ||
return fullsplit(head, [tail] + result) | ||
|
||
|
||
def find_packages(package_dir): | ||
""" | ||
Returns a tuple consisting of a ``packages`` list and a ``package_data`` | ||
dictionary suitable for passing on to ``distutils.core.setup`` | ||
Requires the folder name containing the package files; ``find_files`` | ||
assumes that ``setup.py`` is located in the same folder as the folder | ||
containing those files. | ||
Code lifted from Django's ``setup.py``, with improvements by PSyton. | ||
""" | ||
|
||
# Compile the list of packages available, because distutils doesn't have | ||
# an easy way to do this. | ||
packages = [] | ||
package_data = {} | ||
root_dir = os.path.dirname(__file__) | ||
if root_dir != '': | ||
os.chdir(root_dir) | ||
|
||
for dirpath, dirnames, filenames in sorted(os.walk(package_dir)): | ||
# Ignore dirnames that start with '.' | ||
for i, dirname in enumerate(dirnames): | ||
if dirname.startswith('.'): del dirnames[i] | ||
if '__init__.py' in filenames: | ||
packages.append('.'.join(fullsplit(dirpath))) | ||
elif filenames: | ||
cur_pack = packages[0] # Assign all data files to the toplevel package | ||
if cur_pack not in package_data: | ||
package_data[cur_pack] = [] | ||
package_dir = os.path.join(*cur_pack.split(".")) | ||
dir_relpath = os.path.relpath(dirpath, package_dir) | ||
for f in filenames: | ||
package_data[cur_pack].append(os.path.join(dir_relpath, f)) | ||
|
||
return packages, package_data | ||
|