From c2d89e3a78e9e43bc3f9e61bf7166ce057d80b56 Mon Sep 17 00:00:00 2001 From: msummers42 Date: Tue, 13 Oct 2009 23:46:04 -0500 Subject: Intial commit. It works, but won't display the images until they are served via an external media server. I will add that in for dev purposes next. --- .gitignore | 5 ++ README | 25 +++++++++ TODO | 17 ++++++ example_ads.py | 108 +++++++++++++++++++++++++++++++++++++ gentoo_ads/__init__.py | 0 gentoo_ads/ads/__init__.py | 0 gentoo_ads/ads/models.py | 3 ++ gentoo_ads/ads/templates/ads.html | 14 +++++ gentoo_ads/ads/tests.py | 23 ++++++++ gentoo_ads/ads/views.py | 30 +++++++++++ gentoo_ads/example_settings.py | 110 ++++++++++++++++++++++++++++++++++++++ gentoo_ads/manage.py | 11 ++++ gentoo_ads/urls.py | 19 +++++++ 13 files changed, 365 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100644 TODO create mode 100644 example_ads.py create mode 100644 gentoo_ads/__init__.py create mode 100644 gentoo_ads/ads/__init__.py create mode 100644 gentoo_ads/ads/models.py create mode 100644 gentoo_ads/ads/templates/ads.html create mode 100644 gentoo_ads/ads/tests.py create mode 100644 gentoo_ads/ads/views.py create mode 100644 gentoo_ads/example_settings.py create mode 100755 gentoo_ads/manage.py create mode 100644 gentoo_ads/urls.py 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 diff --git a/gentoo_ads/ads/__init__.py b/gentoo_ads/ads/__init__.py new file mode 100644 index 0000000..e69de29 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 @@ + + + + + + + + {% for ad in ads %} + {{ ad.title }}
+ {% endfor %} + + + + \ 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)), +) -- cgit v1.2.3-65-gdbad