aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--README25
-rw-r--r--TODO17
-rw-r--r--example_ads.py108
-rw-r--r--gentoo_ads/__init__.py0
-rw-r--r--gentoo_ads/ads/__init__.py0
-rw-r--r--gentoo_ads/ads/models.py3
-rw-r--r--gentoo_ads/ads/templates/ads.html14
-rw-r--r--gentoo_ads/ads/tests.py23
-rw-r--r--gentoo_ads/ads/views.py30
-rw-r--r--gentoo_ads/example_settings.py110
-rwxr-xr-xgentoo_ads/manage.py11
-rw-r--r--gentoo_ads/urls.py19
13 files changed, 365 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6024588
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.pyc
+*.pyo
+*~
+gentoo_ads/settings.py
+
diff --git a/README b/README
new file mode 100644
index 0000000..4948ba4
--- /dev/null
+++ b/README
@@ -0,0 +1,25 @@
+gentoo-ads
+created by Matthew Summers and Richard Anderson of Liquidus Tech, LLC
+
+this is an ads (automated display system)
+written in python and using the django web framework
+
+It is licensed under the GPLv3 or greater.
+
+gentoo-ads has been tested with python-2.6.3 and django-1.1.1
+but should work just fine on python-2.5 and django-1.0.x.
+There are no other direct dependencies.
+
+The gentoo-ads 'ads' module uses a simple random weighted subset method
+to choose the object to display.
+
+To get started simply:
+$ cd gentoo_ads
+$ cp example_settings.py settings.py
+
+Edit the CONFIG_PATH in settings.py to point to your copy of example_ads.py
+
+Then run the django development webserver via
+$ python manage.py runserver
+
+Finally, navigate your browser to http://localhost:8000 to view the display results. \ No newline at end of file
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..e0afbe6
--- /dev/null
+++ b/TODO
@@ -0,0 +1,17 @@
+TODO
+gentoo-ads
+
+show how to serve the static media via dev server
+ create demo images
+
+implement impression counter
+ needs design decision
+ what is the desired output for analysis
+ why not use apache logs?
+
+implement serialized POST to collect clickthru and related JS
+ design decision needed
+ what info from the REQUEST object do we want?
+
+Something else maybe?
+A nice little analytics dashboard ... that could be nice.
diff --git a/example_ads.py b/example_ads.py
new file mode 100644
index 0000000..147228d
--- /dev/null
+++ b/example_ads.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+# most of this stuff is obvious.
+# tier is not currently used
+# weight is whatever integer you want, i.e. bogomips, etc
+
+## note: all images must be named with 'name'.png
+
+ads = [
+ {
+ 'name': 'internal_name_1',
+ 'title': 'human title 1',
+ 'tier': 1,
+ 'weight': 15, #bogomips
+ 'url': 'http://www1.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_2',
+ 'title': 'human title 2',
+ 'tier': 1,
+ 'weight': 25,
+ 'url': 'http://www2.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_3',
+ 'title': 'human title 3',
+ 'tier': 1,
+ 'weight': 5,
+ 'url': 'http://www3.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_4',
+ 'title': 'human title 4',
+ 'tier': 2,
+ 'weight': 105,
+ 'url': 'http://www4.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_5',
+ 'title': 'human title 5',
+ 'tier': 2,
+ 'weight': 19,
+ 'url': 'http://www5.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_6',
+ 'title': 'human title 6',
+ 'tier': 3,
+ 'weight': 150,
+ 'url': 'http://www6.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_7',
+ 'title': 'human title 7',
+ 'tier': 3,
+ 'weight': 170,
+ 'url': 'http://www7.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_8',
+ 'title': 'human title 8',
+ 'tier': 3,
+ 'weight': 11,
+ 'url': 'http://www8.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_9',
+ 'title': 'human title 9',
+ 'tier': 3,
+ 'weight': 1950,
+ 'url': 'http://www9.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_10',
+ 'title': 'human title 10',
+ 'tier': 3,
+ 'weight': 122,
+ 'url': 'http://www10.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+ {
+ 'name': 'internal_name_11',
+ 'title': 'human title 11',
+ 'tier': 3,
+ 'weight': 17,
+ 'url': 'http://www11.example.com',
+ 'height': 120,
+ 'width': 125,
+ },
+]
diff --git a/gentoo_ads/__init__.py b/gentoo_ads/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gentoo_ads/__init__.py
diff --git a/gentoo_ads/ads/__init__.py b/gentoo_ads/ads/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gentoo_ads/ads/__init__.py
diff --git a/gentoo_ads/ads/models.py b/gentoo_ads/ads/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/gentoo_ads/ads/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/gentoo_ads/ads/templates/ads.html b/gentoo_ads/ads/templates/ads.html
new file mode 100644
index 0000000..55a80d2
--- /dev/null
+++ b/gentoo_ads/ads/templates/ads.html
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <title></title>
+ <meta content="">
+ <style></style>
+ </head>
+ <body>
+ {% for ad in ads %}
+ <a href="{{ad.url}}"><img src="{{ MEDIA_URL }}{{ ad.name }}.png" alt="{{ ad.title }}" title="{{ ad.title }}" height="{{ ad.height }}" width="{{ ad.width }}" /></a><br />
+ {% endfor %}
+
+
+ </body>
+</html> \ No newline at end of file
diff --git a/gentoo_ads/ads/tests.py b/gentoo_ads/ads/tests.py
new file mode 100644
index 0000000..2247054
--- /dev/null
+++ b/gentoo_ads/ads/tests.py
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/gentoo_ads/ads/views.py b/gentoo_ads/ads/views.py
new file mode 100644
index 0000000..c98968d
--- /dev/null
+++ b/gentoo_ads/ads/views.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Create your views here.
+
+from django.shortcuts import render_to_response
+from django.conf import settings
+from random import randint
+
+def serve_ads(request):
+ sample = _weighted_random_sample(settings.ADS_STRUCT)
+ return render_to_response('ads.html', {'ads': sample, 'MEDIA_URL': settings.MEDIA_URL,})
+
+def _weighted_random_sample(ads):
+ ads_out = []
+
+ for i in xrange(settings.ADS_LENGTH):
+ indices = [a['weight'] for a in ads]
+ s = sum(indices)
+ r = randint(0, s-1)
+ cur_total = 0
+
+ for ad_i in xrange(len(ads)):
+ ad = ads[ad_i]
+ cur_total += ad['weight']
+
+ if r < cur_total:
+ ads_out.append(ad)
+ ads = ads[:ad_i] + ads[ad_i + 1:]
+ break
+
+ return ads_out \ No newline at end of file
diff --git a/gentoo_ads/example_settings.py b/gentoo_ads/example_settings.py
new file mode 100644
index 0000000..f76c474
--- /dev/null
+++ b/gentoo_ads/example_settings.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+# Django settings for gentoo_ads project.
+
+## created by Matthew Summers aka quantumsummers for Gentoo Linux
+## I suppose gplv3 is a nice license for this software, so be it.
+## If someone else every uses this, feel free to contact me via
+## quantumsummers at the gentoo dot org domain.
+
+from imp import load_source
+import os
+
+## this is the path to the file containing your advertiser dictionaries.
+## please note, in general the ads.py file should live outside the webroot.
+CONFIG_PATH = '/some/path/towards/the/file/gentoo-ads/example_ads.py'
+
+## nifty, facilitates use of advertiser dictionary
+## loads a python module living somwhere on the machine
+## though if it finds a good .pyc|o it will use it first
+ads_module = load_source('ads_module', CONFIG_PATH,)
+
+## sets the number of ads to be displayed
+ADS_LENGTH = 6
+
+## why is this not above ADS_LENGTH?
+## list of dictionaries we use in the view, i,e, the advertisements.
+ADS_STRUCT = ads_module.ads
+
+## this should really be an absolute path in production,
+## also eliminating the `import os` above
+ADS_IMAGES_DIR = os.path.join(os.path.dirname(CONFIG_PATH), 'images')
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+## this will email errors when DEBUG=FALSE
+ADMINS = ()
+ # ('Your Name', 'your_email@domain.com'),
+
+
+MANAGERS = ADMINS
+
+## needs no DB at this point
+#DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+#DATABASE_NAME = '' # Or path to database file if using sqlite3.
+#DATABASE_USER = '' # Not used with sqlite3.
+#DATABASE_PASSWORD = '' # Not used with sqlite3.
+#DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+#DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = False
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+#MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+
+## this is hypothecal at this time
+MEDIA_URL = 'http://media.example.com/img/'
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'v1nht7uj01_btjz4!&2%8(xq!$gao%80&r1w=h#ij17*@+-$3k'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.app_directories.load_template_source',
+)
+
+TEMPLATE_CONTEXT_PROCESSORS = ()
+
+MIDDLEWARE_CLASSES = ()
+
+ROOT_URLCONF = 'gentoo_ads.urls'
+
+## not needed using the above template loader
+TEMPLATE_DIRS = ()
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+
+
+## we have but one
+## app this day
+## perhaps another
+## tomorrow
+INSTALLED_APPS = (
+ 'ads',
+)
diff --git a/gentoo_ads/manage.py b/gentoo_ads/manage.py
new file mode 100755
index 0000000..5e78ea9
--- /dev/null
+++ b/gentoo_ads/manage.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
diff --git a/gentoo_ads/urls.py b/gentoo_ads/urls.py
new file mode 100644
index 0000000..d1c345b
--- /dev/null
+++ b/gentoo_ads/urls.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('',
+ (r'^$', 'ads.views.serve_ads', {}, 'serve-ads'),
+ # Example:
+ # (r'^gentoo_ads/', include('gentoo_ads.foo.urls')),
+
+ # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
+ # to INSTALLED_APPS to enable admin documentation:
+ # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+ # Uncomment the next line to enable the admin:
+ # (r'^admin/', include(admin.site.urls)),
+)