changeset 43:ab83b727d97f

Getting rid of the SiteConfig model.
author Brian Neal <bgneal@gmail.com>
date Sun, 11 Mar 2012 14:29:42 -0500
parents 82f65fb5e260
children 42a6bde9913c
files madeira/band/admin.py madeira/band/admin_views.py madeira/band/models.py madeira/band/urls.py madeira/band/views.py madeira/settings/base.py madeira/settings/production.py madeira/templates/band/base.html madeira/templates/band/buy.html madeira/templates/band/contact.html madeira/templates/band/email_subscribe.txt madeira/templates/band/email_unsubscribe.txt madeira/templates/band/index.html madeira/templates/band/press.html
diffstat 14 files changed, 333 insertions(+), 400 deletions(-) [+]
line wrap: on
line diff
--- a/madeira/band/admin.py	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/band/admin.py	Sun Mar 11 14:29:42 2012 -0500
@@ -1,9 +1,7 @@
-#######################################################################
-#
-# PyBand Copyright (C) 2008 by Brian Neal
-#
-#######################################################################
+"""
+Automatic admin definitions for the band models.
 
+"""
 from django.contrib import admin
 
 from band.models import Article
@@ -23,39 +21,20 @@
 from band.models import Mp3_Set
 from band.models import News
 from band.models import Record_Label
-from band.models import SiteConfig
 from band.models import State
 from band.models import Venue
 from band.models import Video
 from band.models import Video_Set
 
-#######################################################################
-
-admin.site.register(Video)
-
-#######################################################################
-
-class SiteConfigAdmin(admin.ModelAdmin):
-   list_display = ('band_name', 'url', 'contact_email')
-   fieldsets = (
-         (None, { 'fields' : ('band_name', 'url', 'contact_email', 'intro_text', 'ordering_info',
-            'intro_photo') }),
-      )
-
-admin.site.register(SiteConfig, SiteConfigAdmin)
-
-#######################################################################
 
 class GearInline(admin.TabularInline):
    model = Gear
 
+
 class GearAdmin(admin.ModelAdmin):
    list_display = ('item', 'member')
    list_filter = ('member', )
 
-admin.site.register(Gear, GearAdmin)
-
-#######################################################################
 
 class MemberAdmin(admin.ModelAdmin):
    list_display = ('name', 'instrument', 'is_active')
@@ -63,59 +42,38 @@
          GearInline,
    ]
 
-admin.site.register(Member, MemberAdmin)
-
-#######################################################################
 
 class CityInline(admin.TabularInline):
    model = City
 
+
 class CityAdmin(admin.ModelAdmin):
    list_display = ('name', 'state', 'country')
    list_filter = ('state', )
    search_fields = ('name', )
 
-admin.site.register(City, CityAdmin)
-
-#######################################################################
-
-admin.site.register(Country)
-
-#######################################################################
 
 class StateAdmin(admin.ModelAdmin):
    inlines = [
          CityInline,
    ]
 
-admin.site.register(State, StateAdmin)
-
-#######################################################################
 
 class VenueAdmin(admin.ModelAdmin):
    list_filter = ('city', )
    list_display = ('name', 'city', )
    search_fields = ('name', )
 
-admin.site.register(Venue, VenueAdmin)
-
-#######################################################################
 
 class BandAdmin(admin.ModelAdmin):
    search_fields = ('name', )
 
-admin.site.register(Band, BandAdmin)
-
-#######################################################################
 
 class GigAdmin(admin.ModelAdmin):
    list_filter = ('date', 'venue')
    save_on_top = True
    filter_horizontal = ('bands', )
 
-admin.site.register(Gig, GigAdmin)
-
-#######################################################################
 
 class NewsAdmin(admin.ModelAdmin):
    save_on_top = True
@@ -123,9 +81,6 @@
    list_display = ('date', 'title')
    search_fields = ('text', 'title')
 
-admin.site.register(News, NewsAdmin)
-
-#######################################################################
 
 class ArticleAdmin(admin.ModelAdmin):
    save_on_top = True
@@ -133,19 +88,14 @@
    list_display = ('title', 'date')
    search_fields = ('text', 'title')
 
-admin.site.register(Article, ArticleAdmin)
-
-#######################################################################
 
 class Mp3Inline(admin.TabularInline):
    model = Mp3
 
+
 class Mp3Admin(admin.ModelAdmin):
    prepopulated_fields = {'slug' : ('title', 'desc')}
 
-admin.site.register(Mp3, Mp3Admin)
-
-#######################################################################
 
 class Mp3_SetAdmin(admin.ModelAdmin):
    list_filter = ('date', )
@@ -154,13 +104,11 @@
          Mp3Inline,
    ]
 
-admin.site.register(Mp3_Set, Mp3_SetAdmin)
-
-#######################################################################
 
 class VideoInline(admin.TabularInline):
    model = Video
 
+
 class Video_SetAdmin(admin.ModelAdmin):
    list_filter = ('date', )
    list_display = ('title', 'date')
@@ -168,51 +116,39 @@
          VideoInline,
    ]
 
-admin.site.register(Video_Set, Video_SetAdmin)
-
-#######################################################################
 
 class Album_TrackInline(admin.TabularInline):
    model = Album_Track
 
+
 class Album_TrackAdmin(admin.ModelAdmin):
    list_display = ('track_name', 'album')
    list_filter = ('album', )
 
-admin.site.register(Album_Track, Album_TrackAdmin)
-
-#######################################################################
 
 class Label_ReleaseInline(admin.TabularInline):
    model = Label_Release
 
+
 class Label_ReleaseAdmin(admin.ModelAdmin):
    list_display = ('catalog_number', 'album', 'record_label', 'release_date')
    list_filter = ('record_label', 'album')
 
-admin.site.register(Label_Release, Label_ReleaseAdmin)
-
-#######################################################################
 
 class Record_LabelAdmin(admin.ModelAdmin):
    inlines = [
          Label_ReleaseInline,
    ]
 
-admin.site.register(Record_Label, Record_LabelAdmin)
-
-#######################################################################
 
 class Album_MerchantInline(admin.TabularInline):
    model = Album_Merchant
 
+
 class Album_MerchantAdmin(admin.ModelAdmin):
    list_display = ('name', 'album')
    list_filter = ('album', )
 
-admin.site.register(Album_Merchant, Album_MerchantAdmin)
-
-#######################################################################
 
 class AlbumAdmin(admin.ModelAdmin):
    save_on_top = True
@@ -222,23 +158,35 @@
          Album_MerchantInline,
    ]
 
-admin.site.register(Album, AlbumAdmin)
-
-#######################################################################
 
 class MerchandiseAdmin(admin.ModelAdmin):
    list_display = ('name', 'price', 'in_stock')
    list_filter = ('in_stock', )
 
-admin.site.register(Merchandise, MerchandiseAdmin)
-
-#######################################################################
 
 class FanAdmin(admin.ModelAdmin):
    list_display = ('name', 'email', 'current_status')
    search_fields = ('name', 'email')
 
+
+admin.site.register(Video)
+admin.site.register(Gear, GearAdmin)
+admin.site.register(Member, MemberAdmin)
+admin.site.register(City, CityAdmin)
+admin.site.register(Country)
+admin.site.register(State, StateAdmin)
+admin.site.register(Venue, VenueAdmin)
+admin.site.register(Band, BandAdmin)
+admin.site.register(Gig, GigAdmin)
+admin.site.register(News, NewsAdmin)
+admin.site.register(Article, ArticleAdmin)
+admin.site.register(Mp3, Mp3Admin)
+admin.site.register(Mp3_Set, Mp3_SetAdmin)
+admin.site.register(Video_Set, Video_SetAdmin)
+admin.site.register(Album_Track, Album_TrackAdmin)
+admin.site.register(Label_Release, Label_ReleaseAdmin)
+admin.site.register(Record_Label, Record_LabelAdmin)
+admin.site.register(Album_Merchant, Album_MerchantAdmin)
+admin.site.register(Album, AlbumAdmin)
+admin.site.register(Merchandise, MerchandiseAdmin)
 admin.site.register(Fan, FanAdmin)
-
-#######################################################################
-
--- a/madeira/band/admin_views.py	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/band/admin_views.py	Sun Mar 11 14:29:42 2012 -0500
@@ -1,8 +1,7 @@
-#######################################################################
-#
-# PyBand Copyright (C) 2008 by Brian Neal
-#
-#######################################################################
+"""
+Admin views for the Madeira website.
+
+"""
 from django import forms
 from django.core.urlresolvers import reverse
 from django.core.mail import EmailMessage
@@ -10,8 +9,8 @@
 from django.http import HttpResponseRedirect
 from django.shortcuts import render_to_response
 from django.contrib.admin.views.decorators import staff_member_required
+from django.conf import settings
 
-from band.models import SiteConfig
 from band.models import Fan
 
 #######################################################################
@@ -26,52 +25,48 @@
 #######################################################################
 
 class EmailForm(forms.Form):
-   subject = forms.CharField(max_length = 255, required = True, label = 'Subject:',
-         widget = forms.TextInput(attrs = {'class' : 'vTextField required', 'size' : '60'}))
-   message = forms.CharField(label = 'Message:',
-         widget = forms.Textarea(attrs = {'class' : 'vLargeTextField required'}))
+    subject = forms.CharField(max_length=255, required=True, label='Subject:',
+        widget=forms.TextInput(attrs={'class': 'vTextField required', 'size': '60'}))
+    message = forms.CharField(label='Message:',
+        widget=forms.Textarea(attrs={'class': 'vLargeTextField required'}))
 
 #######################################################################
 
 def email_sent(request):
-   return render_to_response('admin/band/email_sent.html',
-         {},
-         context_instance = RequestContext(request))
+    return render_to_response('admin/band/email_sent.html', {},
+        context_instance=RequestContext(request))
 
 #######################################################################
 
 def email(request):
 
-   config = SiteConfig.objects.get(pk = 1)
-   bandTag = '[%s] ' % (config.band_name, )
+    config = settings.BAND_CONFIG
+    bandTag = '[%s] ' % config['BAND_NAME']
 
-   if request.method == 'POST':
-      form = EmailForm(request.POST)
-      if form.is_valid():
-         subject = form.cleaned_data['subject']
-         message = form.cleaned_data['message']
+    if request.method == 'POST':
+        form = EmailForm(request.POST)
+        if form.is_valid():
+            subject = form.cleaned_data['subject']
+            message = form.cleaned_data['message']
 
-         unsubscribeUrl = config.url
-         if unsubscribeUrl[-1] != '/':
-            unsubscribeUrl += '/'
-         unsubscribeUrl += 'mail'
+            unsubscribe_url = "http://%s%s" % (config['BAND_DOMAIN'],
+                      reverse('band-mail'))
 
-         footer = unsubscribeText % (unsubscribeUrl, )
-         message += footer
-         
-         fans = Fan.objects.all()
-         bcc = [fan.email for fan in fans]
+            footer = unsubscribeText % unsubscribe_url
+            message += footer
+            
+            bcc = list(Fan.objects.values_list('email', flat=True))
 
-         email = EmailMessage(subject, message, config.contact_email,
-               [config.contact_email], bcc)
-         email.send()
-         return HttpResponseRedirect(reverse(email_sent))
+            email = EmailMessage(subject, message, config['BAND_EMAIL'],
+                    [config['BAND_EMAIL']], bcc)
+            email.send()
+            return HttpResponseRedirect(reverse(email_sent))
 
-   else:
-      form = EmailForm(initial = { 'subject' : bandTag })
+    else:
+        form = EmailForm(initial={'subject': bandTag})
 
-   return render_to_response('admin/band/email.html',
-         { 'form' : form },
-         context_instance = RequestContext(request))
+    return render_to_response('admin/band/email.html',
+            {'form': form },
+            context_instance=RequestContext(request))
 
 email = staff_member_required(email)
--- a/madeira/band/models.py	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/band/models.py	Sun Mar 11 14:29:42 2012 -0500
@@ -9,23 +9,6 @@
 
 #######################################################################
 
-class SiteConfig(models.Model):
-   band_name = models.CharField(max_length = 50)
-   url = models.URLField(verify_exists = False, max_length = 200)
-   contact_email = models.EmailField()
-   ordering_info = models.TextField(help_text = 'Enter instructions on how to order merchandise here')
-   intro_text = models.TextField(help_text = 'This text appears on the home page.')
-   intro_photo = models.ForeignKey(Photo)
-
-   def __unicode__(self):
-      return self.band_name
-
-   class Meta:
-      verbose_name = "Site Configuration"
-      verbose_name_plural = "Site Configuration"
-
-#######################################################################
-
 class Member(models.Model):
    name = models.CharField(max_length = 50, db_index = True)
    nickname = models.CharField(max_length = 50, blank = True)
--- a/madeira/band/urls.py	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/band/urls.py	Sun Mar 11 14:29:42 2012 -0500
@@ -7,8 +7,8 @@
    (r'^contact/$', 'contact'),
    (r'^gigs/$', 'gigs'),
    (r'^gigs/flyers$', 'flyers'),
-   (r'^mail/$', 'mail'),
-   (r'^mail/confirm/([a-zA-Z0-9]+)$', 'mail_confirm'),
+   url(r'^mail/$', 'mail', name='band-mail'),
+   url(r'^mail/confirm/([a-zA-Z0-9]+)$', 'mail_confirm', name='band-mail_confirm'),
    (r'^mail/not_found$', 'mail_not_found'),
    (r'^mail/thanks$', 'mail_thanks'),
    (r'^mail/unsubscribe$', 'mail_unsubscribe'),
--- a/madeira/band/views.py	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/band/views.py	Sun Mar 11 14:29:42 2012 -0500
@@ -1,8 +1,7 @@
-#######################################################################
-#
-# PyBand Copyright (C) 2008 - 2011 by Brian Neal
-#
-#######################################################################
+"""
+Views for the band application.
+
+"""
 import collections
 import datetime
 import random
@@ -16,6 +15,7 @@
 from django.template.loader import render_to_string
 from django.core.mail import send_mail
 from django.db import connection
+from django.conf import settings
 
 from band.models import Article
 from band.models import Album
@@ -26,7 +26,6 @@
 from band.models import Merchandise
 from band.models import Mp3_Set
 from band.models import News
-from band.models import SiteConfig
 from band.models import Video_Set
 from photologue.models import Gallery
 from photologue.models import Photo
@@ -34,304 +33,304 @@
 #######################################################################
 
 def index(request):
-   config = SiteConfig.objects.get(pk = 1)
-   carpe = Photo.objects.get(title_slug = 'carpe-noctem')
-   sandstorm = Photo.objects.get(title_slug = 'sandstorm-cover')
-   ruins = Photo.objects.get(title_slug = 'ruins-cover')
+    carpe = Photo.objects.get(title_slug = 'carpe-noctem')
+    sandstorm = Photo.objects.get(title_slug = 'sandstorm-cover')
+    ruins = Photo.objects.get(title_slug = 'ruins-cover')
 
-   upcomingDates = Gig.objects.filter(date__gte = datetime.date.today).order_by('date')[:5]
+    upcomingDates = Gig.objects.filter(date__gte = datetime.date.today).order_by('date')[:5]
 
-   return render_to_response('band/index.html',
-         { 
-           'config' : config, 
-           'carpe' : carpe,
-           'sandstorm' : sandstorm,
-           'ruins' : ruins,
-           'upcomingDates' : upcomingDates,
-           # 'tourPhotos' : tourPhotos,
+    return render_to_response('band/index.html', { 
+              'carpe' : carpe,
+              'sandstorm' : sandstorm,
+              'ruins' : ruins,
+              'upcomingDates' : upcomingDates,
+            },
+            context_instance = RequestContext(request))
+
+#######################################################################
+
+def bio(request):
+    members = Member.objects.exclude(is_active__exact = 0)
+
+    return render_to_response('band/bio.html', 
+            { 'members' : members, },
+            context_instance = RequestContext(request))
+
+#######################################################################
+
+def gigs(request):
+    today = datetime.date.today()
+    gigs = Gig.objects.select_related('venue', 'flyer', 'venue__city',
+              'venue__city__state', 'venue__city__country')
+    upcoming = []
+    previous = []
+
+    # To avoid many, many database hits in the template, we get all the
+    # bands out at once. We also get the many-to-many intermediate table
+    # that Django generated for us so we can associate bands to gigs.
+    # Since we don't know about this table we drop into raw SQL to get
+    # the contents.
+
+    bands = dict((band.id, band) for band in Band.objects.all())
+    cursor = connection.cursor()
+    cursor.execute('SELECT * FROM band_gig_bands')
+    gig_bands = collections.defaultdict(list)
+    for row in cursor.fetchall():
+        gig_bands[row[1]].append(bands[row[2]])
+
+    for gig in gigs:
+        gig.bands_ = gig_bands[gig.id]
+        if gig.date >= today:
+            upcoming.append(gig)
+        else:
+            previous.append(gig)
+
+    upcoming.reverse()
+
+    stats = {}
+    venues = set()
+    cities = set()
+    states = set()
+    countries = set()
+    for gig in previous:
+        venues.add(gig.venue.id)
+        cities.add(gig.venue.city.id)
+        if gig.venue.city.state:
+            states.add(gig.venue.city.state.id)
+        if gig.venue.city.country:
+            countries.add(gig.venue.city.country.id)
+
+    stats['count'] = len(previous)
+    stats['venues'] = len(venues)
+    stats['cities'] = len(cities)
+    stats['states'] = len(states)
+    stats['countries'] = len(countries)
+    stats['bands'] = len(bands)
+
+    flyerGigs = Gig.objects.exclude(flyer__isnull = True).select_related(
+         'venue', 'flyer').order_by('-date')
+
+    return render_to_response('band/gigs.html', {
+         'upcoming' : upcoming,
+         'previous' : previous,
+         'stats' : stats,
+         'flyerGigs' : flyerGigs,
          },
          context_instance = RequestContext(request))
 
 #######################################################################
 
-def bio(request):
-   members = Member.objects.exclude(is_active__exact = 0)
+def news(request):
+    news = News.objects.order_by('-date')
 
-   return render_to_response('band/bio.html', 
-         { 'members' : members, },
+    return render_to_response('band/news.html',
+            { 
+              'news' : news
+            },
+            context_instance = RequestContext(request))
+
+#######################################################################
+
+def press_index(request):
+    articles = Article.objects.order_by('-date')
+
+    return render_to_response('band/press.html',
+            { 
+              'articles' : articles
+            },
+            context_instance = RequestContext(request))
+
+#######################################################################
+
+def press_detail(request, id):
+    article = get_object_or_404(Article, pk = id)
+
+    return render_to_response('band/press_detail.html',
+            { 'article' : article },
+            context_instance = RequestContext(request))
+
+#######################################################################
+
+def songs(request):
+    mp3Sets = Mp3_Set.objects.order_by('-date', '-id')
+
+    return render_to_response('band/songs.html',
+            { 'mp3Sets' : mp3Sets },
+            context_instance = RequestContext(request))
+
+#######################################################################
+
+def photos_index(request):
+    galleries = Gallery.objects.values('title', 'id').order_by('-id')
+
+    photos = Photo.objects.filter(is_public__exact = 1)
+    randomPhotos = random.sample(photos, 4)
+
+    return render_to_response('band/photos.html',
+            { 'galleries' : galleries, 'randomPhotos' : randomPhotos },
+            context_instance = RequestContext(request))
+
+#######################################################################
+
+def photo_detail(request, id):
+    gallery = get_object_or_404(Gallery, pk = id)
+    photos = gallery.photos.order_by('id')
+    return render_to_response('band/photo_detail.html',
+         {'gallery' : gallery, 'photos': photos },
          context_instance = RequestContext(request))
 
 #######################################################################
 
-def gigs(request):
-   today = datetime.date.today()
-   gigs = Gig.objects.select_related('venue', 'flyer', 'venue__city',
-           'venue__city__state', 'venue__city__country')
-   upcoming = []
-   previous = []
-
-   # To avoid many, many database hits in the template, we get all the
-   # bands out at once. We also get the many-to-many intermediate table
-   # that Django generated for us so we can associate bands to gigs.
-   # Since we don't know about this table we drop into raw SQL to get
-   # the contents.
-
-   bands = dict((band.id, band) for band in Band.objects.all())
-   cursor = connection.cursor()
-   cursor.execute('SELECT * FROM band_gig_bands')
-   gig_bands = collections.defaultdict(list)
-   for row in cursor.fetchall():
-      gig_bands[row[1]].append(bands[row[2]])
-
-   for gig in gigs:
-      gig.bands_ = gig_bands[gig.id]
-      if gig.date >= today:
-         upcoming.append(gig)
-      else:
-         previous.append(gig)
-
-   upcoming.reverse()
-
-   stats = {}
-   venues = set()
-   cities = set()
-   states = set()
-   countries = set()
-   for gig in previous:
-      venues.add(gig.venue.id)
-      cities.add(gig.venue.city.id)
-      if gig.venue.city.state:
-         states.add(gig.venue.city.state.id)
-      if gig.venue.city.country:
-         countries.add(gig.venue.city.country.id)
-
-   stats['count'] = len(previous)
-   stats['venues'] = len(venues)
-   stats['cities'] = len(cities)
-   stats['states'] = len(states)
-   stats['countries'] = len(countries)
-   stats['bands'] = len(bands)
-
-   flyerGigs = Gig.objects.exclude(flyer__isnull = True).select_related(
-       'venue', 'flyer').order_by('-date')
-
-   return render_to_response('band/gigs.html', {
-       'upcoming' : upcoming,
-       'previous' : previous,
-       'stats' : stats,
-       'flyerGigs' : flyerGigs,
-       },
-       context_instance = RequestContext(request))
-
-#######################################################################
-
-def news(request):
-   news = News.objects.order_by('-date')
-
-   return render_to_response('band/news.html',
-         { 
-           'news' : news
-         },
-         context_instance = RequestContext(request))
-
-#######################################################################
-
-def press_index(request):
-   articles = Article.objects.order_by('-date')
-
-   return render_to_response('band/press.html',
-         { 
-           'articles' : articles
-         },
-         context_instance = RequestContext(request))
-
-#######################################################################
-
-def press_detail(request, id):
-   article = get_object_or_404(Article, pk = id)
-
-   return render_to_response('band/press_detail.html',
-         { 'article' : article },
-         context_instance = RequestContext(request))
-
-#######################################################################
-
-def songs(request):
-   mp3Sets = Mp3_Set.objects.order_by('-date', '-id')
-
-   return render_to_response('band/songs.html',
-         { 'mp3Sets' : mp3Sets },
-         context_instance = RequestContext(request))
-
-#######################################################################
-
-def photos_index(request):
-   galleries = Gallery.objects.values('title', 'id').order_by('-id')
-
-   photos = Photo.objects.filter(is_public__exact = 1)
-   randomPhotos = random.sample(photos, 4)
-
-   return render_to_response('band/photos.html',
-         { 'galleries' : galleries, 'randomPhotos' : randomPhotos },
-         context_instance = RequestContext(request))
-
-#######################################################################
-
-def photo_detail(request, id):
-   gallery = get_object_or_404(Gallery, pk = id)
-   photos = gallery.photos.order_by('id')
-   return render_to_response('band/photo_detail.html',
-       {'gallery' : gallery, 'photos': photos },
-       context_instance = RequestContext(request))
-
-#######################################################################
-
 def videos_index(request):
-   vidsets = Video_Set.objects.values('title', 'id').order_by('-date')
-   return render_to_response('band/videos.html',
-         { 'vidsets' : vidsets },
-         context_instance = RequestContext(request))
+    vidsets = Video_Set.objects.values('title', 'id').order_by('-date')
+    return render_to_response('band/videos.html',
+            { 'vidsets' : vidsets },
+            context_instance = RequestContext(request))
 
 #######################################################################
 
 def video_detail(request, id):
-   vidset = get_object_or_404(Video_Set, pk = id)
+    vidset = get_object_or_404(Video_Set, pk = id)
 
-   return render_to_response('band/video_detail.html',
-         { 'vidset' : vidset },
-         context_instance = RequestContext(request))
+    return render_to_response('band/video_detail.html',
+            { 'vidset' : vidset },
+            context_instance = RequestContext(request))
 
 #######################################################################
 
 def buy(request):
-   albums = Album.objects.all().order_by('-id')
-   merchandise = Merchandise.objects.all().order_by('-id')
-   config = SiteConfig.objects.values('ordering_info').get(pk = 1)
-   return render_to_response('band/buy.html',
-         { 'albums' : albums, 'merchandise' : merchandise, 'config' : config },
-         context_instance = RequestContext(request))
+    albums = Album.objects.all().order_by('-id')
+    merchandise = Merchandise.objects.all().order_by('-id')
+    return render_to_response('band/buy.html', { 
+        'albums': albums, 
+        'merchandise': merchandise, 
+        },
+        context_instance=RequestContext(request))
 
 #######################################################################
 
-def confirmEmail(config, to, subscribe, key):
-   band = config.band_name
-   fromEmail = config.contact_email
-   url = config.url
-   if url[-1] != '/':
-      url += '/'
-   url += 'mail/confirm/' + key
+def confirmEmail(to, subscribe, key):
+    config = settings.BAND_CONFIG
+    band = config['BAND_NAME']
+    from_email = config['BAND_EMAIL']
 
-   if subscribe:
-      emailTemplate = 'band/email_subscribe.txt'
-   else:
-      emailTemplate = 'band/email_unsubscribe.txt'
+    url = "http://%s%s" % (config['BAND_DOMAIN'],
+            reverse('band-mail_confirm', args=[key]))
 
-   msg = render_to_string(emailTemplate, { 'band' : band, 'url' : url, 'band_url' : config.url })
+    if subscribe:
+        email_template = 'band/email_subscribe.txt'
+    else:
+        email_template = 'band/email_unsubscribe.txt'
 
-   subject = '[' + band + '] Mailing List Confirmation'
+    msg = render_to_string(email_template, {
+        'band': band, 
+        'url': url, 
+        'band_domain': config['BAND_DOMAIN'],
+        })
 
-   send_mail(subject, msg, fromEmail, [to])
+    subject = "[%s] Mailing List Confirmation" % band
+
+    send_mail(subject, msg, from_email, [to])
 
 #######################################################################
 
 def contact(request):
-   config = SiteConfig.objects.get(pk = 1)
-   band = Member.objects.exclude(is_active__exact = 0).order_by('order')
-   return render_to_response('band/contact.html',
-         { 'config' : config, 'band' : band },
-         context_instance = RequestContext(request))
+    band = Member.objects.exclude(is_active__exact = 0).order_by('order')
+    return render_to_response('band/contact.html', {
+        'band': band,
+        },
+        context_instance=RequestContext(request))
 
 #######################################################################
 
 class ContactForm(forms.Form):
-   name = forms.CharField(max_length = 32, required = False,
-         widget = forms.TextInput(attrs = {'class' : 'form-box'}))
-   email = forms.EmailField(widget = forms.TextInput(attrs = {'class' : 'form-box'}))
-   location = forms.CharField(max_length = 32, required = False,
-         widget = forms.TextInput(attrs = {'class' : 'form-box'}))
-   option = forms.ChoiceField(choices = (('subscribe', 'Subscribe'), ('unsubscribe', 'Unsubscribe')),
-         widget = forms.Select(attrs = {'class' : 'form-box'}))
+    name = forms.CharField(max_length = 32, required = False,
+            widget = forms.TextInput(attrs = {'class' : 'form-box'}))
+    email = forms.EmailField(widget = forms.TextInput(attrs = {'class' : 'form-box'}))
+    location = forms.CharField(max_length = 32, required = False,
+            widget = forms.TextInput(attrs = {'class' : 'form-box'}))
+    option = forms.ChoiceField(choices = (('subscribe', 'Subscribe'), ('unsubscribe', 'Unsubscribe')),
+            widget = forms.Select(attrs = {'class' : 'form-box'}))
 
 def mail(request):
-   config = SiteConfig.objects.get(pk = 1)
-   form = ContactForm()
-   if request.method == 'POST':
-      form = ContactForm(request.POST)
-      if form.is_valid():
-         if form.cleaned_data['option'] == 'unsubscribe':
-            try:
-               fan = Fan.objects.get(email = form.cleaned_data['email'])
-            except Fan.DoesNotExist:
-               return HttpResponseRedirect(reverse(mail_not_found))
+    form = ContactForm()
+    if request.method == 'POST':
+        form = ContactForm(request.POST)
+        if form.is_valid():
+            if form.cleaned_data['option'] == 'unsubscribe':
+                try:
+                    fan = Fan.objects.get(email = form.cleaned_data['email'])
+                except Fan.DoesNotExist:
+                    return HttpResponseRedirect(reverse(mail_not_found))
 
-            fan.setLeaving()
-            fan.save()
-            confirmEmail(config, fan.email, False, fan.key)
-            return HttpResponseRedirect(reverse(mail_unsubscribe))
+                fan.setLeaving()
+                fan.save()
+                confirmEmail(fan.email, False, fan.key)
+                return HttpResponseRedirect(reverse(mail_unsubscribe))
 
-         elif form.cleaned_data['option'] == 'subscribe':
-            try:
-               fan = Fan.objects.get(email = form.cleaned_data['email'])
-            except Fan.DoesNotExist:
-               fan = Fan(name = form.cleaned_data['name'],
-                         email = form.cleaned_data['email'],
-                         location = form.cleaned_data['location'])
+            elif form.cleaned_data['option'] == 'subscribe':
+                try:
+                    fan = Fan.objects.get(email = form.cleaned_data['email'])
+                except Fan.DoesNotExist:
+                    fan = Fan(name = form.cleaned_data['name'],
+                                 email = form.cleaned_data['email'],
+                                 location = form.cleaned_data['location'])
 
-            fan.setPending()
-            fan.save()
-            confirmEmail(config, fan.email, True, fan.key)
-            return HttpResponseRedirect(reverse(mail_thanks))
+                fan.setPending()
+                fan.save()
+                confirmEmail(fan.email, True, fan.key)
+                return HttpResponseRedirect(reverse(mail_thanks))
 
-   return render_to_response('band/mail.html',
-         { 'form' : form },
-         context_instance = RequestContext(request))
+    return render_to_response('band/mail.html',
+            { 'form' : form },
+            context_instance = RequestContext(request))
 
 #######################################################################
 
 def mail_not_found(request):
-   return render_to_response('band/mail_not_found.html',
-         {},
-         context_instance = RequestContext(request))
+    return render_to_response('band/mail_not_found.html',
+            {},
+            context_instance = RequestContext(request))
 
 #######################################################################
 
 def mail_thanks(request):
-   return render_to_response('band/mail_thanks.html',
-         {},
-         context_instance = RequestContext(request))
+    return render_to_response('band/mail_thanks.html',
+            {},
+            context_instance = RequestContext(request))
 
 #######################################################################
 
 def mail_unsubscribe(request):
-   return render_to_response('band/mail_unsubscribe.html',
-         {},
-         context_instance = RequestContext(request))
+    return render_to_response('band/mail_unsubscribe.html',
+            {},
+            context_instance = RequestContext(request))
 
 #######################################################################
 
 def mail_confirm(request, key):
-   fan = get_object_or_404(Fan, key = key)
+    fan = get_object_or_404(Fan, key = key)
 
-   email = fan.email
-   action = 'subscribed'
+    email = fan.email
+    action = 'subscribed'
 
-   if fan.isPending():
-      fan.setActive()
-      fan.save()
-   elif fan.isLeaving():
-      fan.delete()
-      action = 'unsubscribed'
-   
-   return render_to_response('band/mail_confirm.html',
-         { 'email' : email, 'action' : action },
-         context_instance = RequestContext(request))
+    if fan.isPending():
+        fan.setActive()
+        fan.save()
+    elif fan.isLeaving():
+        fan.delete()
+        action = 'unsubscribed'
+    
+    return render_to_response('band/mail_confirm.html',
+            { 'email' : email, 'action' : action },
+            context_instance = RequestContext(request))
 
 #######################################################################
 
 def flyers(request):
 
-   gigs = Gig.objects.exclude(flyer__isnull = True).order_by('-date')
+    gigs = Gig.objects.exclude(flyer__isnull = True).order_by('-date')
 
-   return render_to_response('band/flyers.html',
-         { 'gigs' : gigs },
-         context_instance = RequestContext(request))
+    return render_to_response('band/flyers.html',
+            { 'gigs' : gigs },
+            context_instance = RequestContext(request))
--- a/madeira/settings/base.py	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/settings/base.py	Sun Mar 11 14:29:42 2012 -0500
@@ -117,6 +117,7 @@
 #######################################################################
 # Email
 #######################################################################
+EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
 EMAIL_HOST = 'localhost'
 EMAIL_PORT = 1025
 
@@ -131,3 +132,12 @@
 SESSION_COOKIE_SECURE = False
 SESSION_EXPIRE_AT_BROWSER_CLOSE = False
 SESSION_SAVE_EVERY_REQUEST = False
+
+#######################################################################
+# Basic Madeira band settings
+#######################################################################
+BAND_CONFIG = {
+    'BAND_NAME': 'The Madeira',
+    'BAND_DOMAIN': 'themadeira.net',
+    'BAND_EMAIL': 'themadeira@themadeira.net',
+}
--- a/madeira/settings/production.py	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/settings/production.py	Sun Mar 11 14:29:42 2012 -0500
@@ -37,6 +37,7 @@
 MIDDLEWARE_CLASSES.insert(0, 'django.middleware.cache.UpdateCacheMiddleware')
 MIDDLEWARE_CLASSES.append('django.middleware.cache.FetchFromCacheMiddleware')
 
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
 EMAIL_HOST = 'localhost'
 EMAIL_PORT = 25
 
--- a/madeira/templates/band/base.html	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/templates/band/base.html	Sun Mar 11 14:29:42 2012 -0500
@@ -54,7 +54,7 @@
 </div>
 
 <div id="footer" class="span-24 last">
-Website &copy; 2008 - 2011 by The Madeira <br />
+Website &copy; 2008 - 2012 by The Madeira <br />
 Visit <a href="http://myspace.com/themadeira">The Madeira on Myspace</a><br />
 and <a href="http://facebook.com/themadeira">The Madeira on Facebook</a><br />
 </div>
--- a/madeira/templates/band/buy.html	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/templates/band/buy.html	Sun Mar 11 14:29:42 2012 -0500
@@ -33,8 +33,8 @@
    <br clear="all" />
 {% endfor %}
 {% if merchandise %}
-   <hr />
-   {{ config.ordering_info|safe|linebreaks }}
+<hr />
+<p>Support your favorite band! We may have a Paypal based payment system coming soon. In the meantime, place your orders for t-shirts and stickers by sending an email to <a href="mailto:themadeira@themadeira.net">themadeira@themadeira.net</a>.</p>
 {% endif %}
 {% for item in merchandise %}
    <h2>{{ item.name }}</h2>
--- a/madeira/templates/band/contact.html	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/templates/band/contact.html	Sun Mar 11 14:29:42 2012 -0500
@@ -2,7 +2,7 @@
 {% block title %}The Madeira | Contact{% endblock %}
 {% block content %}
 <h1>Madeira Contact Info</h1>
-<p>For general band inquiries, send email to: <a href="mailto:{{ config.contact_email }}">{{ config.contact_email }}</a>.</p>
+<p>For general band inquiries, send email to: <a href="mailto:themadeira@themadeira.net">themadeira@themadeira.net</a>.</p>
 <p>To contact individual band members:</p>
 <ul>
 {% for member in band %}
--- a/madeira/templates/band/email_subscribe.txt	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/templates/band/email_subscribe.txt	Sun Mar 11 14:29:42 2012 -0500
@@ -5,15 +5,11 @@
 
 If you did not request to join this mailing list, you may ignore this message.
 
-To subscribe to the mailing list, go to the following confirmation URL:
+To subscribe to the mailing list, please go to the following confirmation URL:
 
 {{ url }}
 
-This should take you directly to an email confirmation page. If it does not,
-please copy and paste the full URL into your web browser's address box and
-hit the "Enter" key on your keyboard.
-
 Thanks,
 
 {{ band }}
-{{ band_url }}
+http://{{ band_domain }}
--- a/madeira/templates/band/email_unsubscribe.txt	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/templates/band/email_unsubscribe.txt	Sun Mar 11 14:29:42 2012 -0500
@@ -5,15 +5,11 @@
 
 If you did not request to unsubscribe from this mailing list, you may ignore this message.
 
-To unsubscribe from the mailing list, go to the following confirmation URL:
+To unsubscribe from the mailing list, please go to the following confirmation URL:
 
 {{ url }}
 
-This should take you directly to an email confirmation page. If it does not,
-please copy and paste the full URL into your web browser's address box and
-hit the "Enter" key on your keyboard.
-
 Thanks,
 
 {{ band }}
-{{ band_url }}
+http://{{ band_domain }}
--- a/madeira/templates/band/index.html	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/templates/band/index.html	Sun Mar 11 14:29:42 2012 -0500
@@ -16,9 +16,14 @@
 {% load markup %}
 {% block content %}
 <h1>The Madeira</h1>
-<img class="floatLeftBox" src="{{ config.intro_photo.image.url }}" 
-   alt="{{ config.intro_photo.title }}" title="{{config.intro_photo.title}}" border="0" />
-{{ config.intro_text|textile }}
+<img class="floatLeftBox" src="/media/photologue/photos/2008/Apr/20/band2008.jpg" 
+   alt="The Madeira 2008" title="The Madeira 2008" border="0" />
+
+<p>The Madeira plays surf music born of screaming wind over the sand dunes of the Sahara Desert, deafening echoes of waves pounding the Gibraltar Rock, joyous late-night gypsy dances in the small towns of Andalucia, and exotic cacophony of the Marrakesh town square. It is the surf music of the millennia-old Mediterranean mysteries.</p>
+
+<p>On these pages you will find the latest news from the band, show dates, songs &amp; videos to download, photos, and merchandise information.</p>
+
+<p>Please also visit <a href="http://myspace.com/themadeira">The Madeira on Myspace</a> and <a href="http://facebook.com/themadeira">The Madeira on Facebook</a>. Send us email at: <a href="mailto:themadeira@themadeira.net">themadeira@themadeira.net</a>.</p>
 <br />
 
 {% if upcomingDates %}
--- a/madeira/templates/band/press.html	Wed Feb 15 19:27:08 2012 -0600
+++ b/madeira/templates/band/press.html	Sun Mar 11 14:29:42 2012 -0500
@@ -4,7 +4,7 @@
 {% block content %}
 <h1>Madeira Press, Articles, &amp; Reviews</h1>
 {% if articles %}
-   <a name="Contents">&nbsp;</a>
+   <a name="Contents"></a>
    <h2>Contents</h2>
    <ul>
    {% for article in articles %}