changeset 44:42a6bde9913c

For ticket #1, create a separate gigs application.
author Brian Neal <bgneal@gmail.com>
date Mon, 12 Mar 2012 16:57:38 -0500
parents ab83b727d97f
children 966cde8635c0
files madeira/band/urls.py madeira/gigs/__init__.py madeira/gigs/admin.py madeira/gigs/models.py madeira/gigs/templatetags/__init__.py madeira/gigs/templatetags/gig_tags.py madeira/gigs/urls.py madeira/gigs/views.py madeira/settings/base.py madeira/templates/band/index.html madeira/templates/gigs/flyers.html madeira/templates/gigs/gigs.html madeira/templates/gigs/upcoming_gigs_tag.html madeira/urls.py
diffstat 12 files changed, 496 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/madeira/band/urls.py	Sun Mar 11 14:29:42 2012 -0500
+++ b/madeira/band/urls.py	Mon Mar 12 16:57:38 2012 -0500
@@ -1,12 +1,12 @@
-from django.conf.urls.defaults import *
+from django.conf.urls.defaults import patterns, url
 
 urlpatterns = patterns('band.views',
    (r'^$', 'index'),
    (r'^bio/$', 'bio'),
    (r'^buy/$', 'buy'),
    (r'^contact/$', 'contact'),
-   (r'^gigs/$', 'gigs'),
-   (r'^gigs/flyers$', 'flyers'),
+   (r'^gigs_old/$', 'gigs'),
+   (r'^gigs_old/flyers$', 'flyers'),
    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'),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/madeira/gigs/admin.py	Mon Mar 12 16:57:38 2012 -0500
@@ -0,0 +1,57 @@
+"""
+Automatic admin definitions for the gigs application.
+
+"""
+from django.contrib import admin
+
+from gigs.models import Band, City, Country, Gig, State, Venue
+
+
+class CityInline(admin.TabularInline):
+    model = City
+
+
+class CityAdmin(admin.ModelAdmin):
+    list_display = ['name', 'state', 'country']
+    list_filter = ['state']
+    search_fields = ['name']
+
+    def queryset(self, request):
+        qs = super(CityAdmin, self).queryset(request)
+        return qs.select_related('state', 'country')
+
+
+class StateAdmin(admin.ModelAdmin):
+    inlines = [CityInline]
+
+
+class VenueAdmin(admin.ModelAdmin):
+    list_filter = ['city__name']
+    list_display = ['name', 'city']
+    search_fields = ['name']
+
+    def queryset(self, request):
+        qs = super(VenueAdmin, self).queryset(request)
+        return qs.select_related('city', 'city__state', 'city__country')
+
+
+class BandAdmin(admin.ModelAdmin):
+    search_fields = ['name']
+
+
+class GigAdmin(admin.ModelAdmin):
+    list_filter = ['date']
+    save_on_top = True
+    filter_horizontal = ['bands']
+
+    def queryset(self, request):
+        qs = super(GigAdmin, self).queryset(request)
+        return qs.select_related('venue')
+
+
+admin.site.register(Band, BandAdmin)
+admin.site.register(City, CityAdmin)
+admin.site.register(Country)
+admin.site.register(Gig, GigAdmin)
+admin.site.register(State, StateAdmin)
+admin.site.register(Venue, VenueAdmin)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/madeira/gigs/models.py	Mon Mar 12 16:57:38 2012 -0500
@@ -0,0 +1,97 @@
+"""
+Models for the gigs application.
+
+"""
+from django.db import models
+from django.contrib.localflavor.us.models import USStateField
+from django.contrib.localflavor.us.models import PhoneNumberField
+
+from photologue.models import Photo
+
+
+class Country(models.Model):
+    name = models.CharField(max_length=64)
+
+    class Meta:
+        ordering = ['name']
+        verbose_name_plural = 'Countries'
+
+    def __unicode__(self):
+        return self.name
+
+
+class State(models.Model):
+    name = models.CharField(max_length=16)
+    abbrev = USStateField()
+
+    class Meta:
+        ordering = ['name']
+
+    def __unicode__(self):
+        return self.name
+
+
+class City(models.Model):
+    name = models.CharField(max_length=50)
+    state = models.ForeignKey(State, null=True, blank=True)
+    country = models.ForeignKey(Country, null=True, blank=True)
+
+    class Meta:
+        verbose_name_plural = 'Cities'
+        ordering = ['name']
+
+    def __unicode__(self):
+        if self.state:
+            return u'%s, %s' % (self.name, self.state.abbrev)
+        
+        return self.name
+
+
+class Venue(models.Model):
+    name = models.CharField(max_length=50)
+    url = models.URLField(verify_exists=False, blank=True)
+    address = models.CharField(max_length=255, blank=True)
+    phone = PhoneNumberField(help_text="Format: XXX-XXX-XXXX", blank=True)
+    city = models.ForeignKey(City)
+
+    class Meta:
+        ordering = ['name']
+
+    def __unicode__(self):
+        return self.name
+
+
+class Band(models.Model):
+    name = models.CharField(max_length=64)
+    url = models.URLField(verify_exists=False, blank=True)
+
+    class Meta:
+        ordering = ['name']
+
+    def __unicode__(self):
+        return self.name
+
+
+class Gig(models.Model):
+    title = models.CharField(max_length=50, blank=True,
+            help_text="Optional; e.g. Some Festival")
+    url = models.URLField(verify_exists=False, blank=True,
+            help_text="Optional; e.g. Some Festival's Website")
+    date = models.DateField(db_index=True)
+    time = models.TimeField(null=True, blank=True)
+    venue = models.ForeignKey(Venue, null=True, blank=True)
+    notes = models.TextField(blank=True)
+    bands = models.ManyToManyField(Band, blank=True)
+    flyer = models.ForeignKey(Photo, null=True, blank=True,
+            related_name='gig_flyers')
+
+    def __unicode__(self):
+        if self.title:
+            return u'%s %s %s' % (self.date.strftime('%m/%d/%Y'), self.title, self.venue.name)
+        elif self.venue:
+            return u'%s %s' % (self.date.strftime('%m/%d/%Y'), self.venue.name)
+        else:
+            return self.date.strftime('%m/%d/%Y')
+
+    class Meta:
+        ordering = ['-date', 'time']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/madeira/gigs/templatetags/gig_tags.py	Mon Mar 12 16:57:38 2012 -0500
@@ -0,0 +1,22 @@
+"""
+Template tags for the gigs application.
+
+"""
+import datetime
+
+from django import template
+
+from gigs.models import Gig
+
+
+register = template.Library()
+
+
+@register.inclusion_tag('gigs/upcoming_gigs_tag.html')
+def upcoming_gigs():
+
+    gigs = Gig.objects.filter(date__gte=datetime.date.today).select_related(
+        'flyer', 'venue', 'venue__city', 'venue__city__state',
+        'venue__city__country').order_by('date')[:10]
+
+    return {'gigs': gigs}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/madeira/gigs/urls.py	Mon Mar 12 16:57:38 2012 -0500
@@ -0,0 +1,19 @@
+"""
+Urls for the gigs application.
+
+"""
+from django.conf.urls.defaults import patterns, url
+from django.views.generic import ListView
+
+from gigs.models import Gig
+
+
+urlpatterns = patterns('',
+   url(r'^$', 'gigs.views.gigs', name='gigs-index'),
+   url(r'^flyers/$',
+       ListView.as_view(
+           queryset=Gig.objects.exclude(flyer__isnull=True).select_related('flyer'),
+           template_name='gigs/flyers.html',
+           context_object_name='gig_list'),
+       name='gigs-flyers')
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/madeira/gigs/views.py	Mon Mar 12 16:57:38 2012 -0500
@@ -0,0 +1,76 @@
+"""
+Views for the gigs application.
+
+"""
+import collections
+import datetime
+
+from django.db import connection
+from django.shortcuts import render
+
+from gigs.models import Band, Gig
+
+
+def gigs(request):
+    """
+    This view function renders the main gigs view, showing upcoming and past
+    gigs as well as some statistics.
+
+    """
+    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)
+
+    flyer_gigs = Gig.objects.exclude(flyer__isnull = True).select_related(
+         'venue', 'flyer').order_by('-date')
+
+    return render(request, 'gigs/gigs.html', {
+         'upcoming' : upcoming,
+         'previous' : previous,
+         'stats' : stats,
+         'flyer_gigs' : flyer_gigs,
+         })
--- a/madeira/settings/base.py	Sun Mar 11 14:29:42 2012 -0500
+++ b/madeira/settings/base.py	Mon Mar 12 16:57:38 2012 -0500
@@ -106,6 +106,7 @@
     'django.contrib.sites',
     'django.contrib.staticfiles',
     'band',
+    'gigs',
     'photologue',
 ]
 
--- a/madeira/templates/band/index.html	Sun Mar 11 14:29:42 2012 -0500
+++ b/madeira/templates/band/index.html	Mon Mar 12 16:57:38 2012 -0500
@@ -1,5 +1,6 @@
 {% extends 'band/base.html' %}
 {% load url from future %}
+{% load gig_tags %}
 {% block title %}The Madeira{% endblock %}
 {% block custom_css %}
 <link rel="stylesheet" href="{{ STATIC_URL }}js/fancybox/jquery.fancybox-1.3.1.css" type="text/css" media="screen" />
@@ -26,35 +27,7 @@
 <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 %}
-<div class="center-block">
-<h2>Upcoming Shows...</h2>
- 
-<center><table border="0" cellspacing="10" cellpadding="3"><tr>
-{% for gig in upcomingDates %}
-   {% if gig.flyer %}
-   <td>
-   <a href="{{ gig.flyer.image.url }}" class="fancybox" rel="madeira-gallery">
-      <img src="{{ gig.flyer.get_thumbnail_url }}" alt="{{ gig.flyer.caption }}" title="{{ gig.flyer.caption }}" /></a>
-   <br /><center>{{ gig.flyer.caption }}</center>
-   </td>
-   {% endif %}
-{% endfor %}
-</tr></table></center>
-
-<ul>
-{% for show in upcomingDates %}
-<li><strong>{{ show.date|date:"l, F d" }}</strong>: {{ show.venue.name }}, {{ show.venue.city.name }}{% if show.venue.city.state %}, {{ show.venue.city.state.name }}
-{% endif %}
-{% ifnotequal show.venue.city.country.name "USA" %}
-{{ show.venue.city.country.name }}
-{% endifnotequal %}
-</li>
-{% endfor %}
-</ul>
-<center><a href="{% url 'band.views.gigs' %}">See all upcoming shows...</a></center>
-</div>
-{% endif %}
+{% upcoming_gigs %}
 
 <div>
    <center>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/madeira/templates/gigs/flyers.html	Mon Mar 12 16:57:38 2012 -0500
@@ -0,0 +1,20 @@
+{% extends 'band/base.html' %}
+{% block title %}The Madeira | Flyer Gallery{% endblock %}
+{% block content %}
+<h1>Show Flyer Gallery</h1>
+{% if gig_list %}
+   <center>
+   {% for gig in gig_list %}
+      <p>
+      {% if gig.title %}
+      <img src="{{ gig.flyer.image.url }}" alt="{{ gig.title }}" title="{{ gig.title }} : {{ gig.date|date:"F d, Y" }}" />
+      {% else %}
+      <img src="{{ gig.flyer.image.url }}" alt="{{ gig.date|date:"F d, Y" }}" title="{{ gig.date|date:"F d, Y" }}" />
+      {% endif %}
+      </p>
+   {% endfor %}
+   </center>
+{% else %}
+<p>No flyers available at this time.</p>
+{% endif %}
+{% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/madeira/templates/gigs/gigs.html	Mon Mar 12 16:57:38 2012 -0500
@@ -0,0 +1,166 @@
+{% extends 'band/base.html' %}
+{% load url from future %}
+{% block title %}The Madeira | Shows{% endblock %}
+{% block custom_css %}
+<link rel="stylesheet" href="{{ STATIC_URL }}js/fancybox/jquery.fancybox-1.3.1.css" type="text/css" media="screen" />
+{% endblock %}
+{% block custom_js %}
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
+<script type="text/javascript" src="{{ STATIC_URL }}js/fancybox/jquery.fancybox-1.3.1.pack.js"></script>
+<script type="text/javascript">
+$(function() {
+   $('a.fancybox').fancybox();
+});
+</script>
+{% endblock %}
+{% block content %}
+<h1>Show Dates</h1>
+
+<h2>Upcoming Shows</h2>
+{% if upcoming %}
+   {% for show in upcoming %}
+      <p style="clear:both">
+      {% if show.flyer %}
+         <a href="{{ show.flyer.image.url }}" class="fancybox" rel="madeira-gallery">
+            <!-- <img style="float:left; margin-right:5px; margin-bottom:1em" src="{{ show.flyer.get_thumbnail_url }}" -->
+            <img class="left" src="{{ show.flyer.get_thumbnail_url }}" 
+               alt="{{ show.flyer.caption }}" title="{{ show.flyer.caption }}" /></a>
+      {% endif %}
+      <strong>{{ show.date|date:"F d, Y" }}</strong>
+      {% if show.time %}{{ show.time|time:"h:i A" }}{% endif %}<br />
+
+      {% if show.title and show.url %}
+         <a href="{{ show.url }}" target="_blank">{{ show.title }}</a><br />
+      {% else %}
+         {% if show.title %}
+            {{ show.title }}<br />
+         {% endif %}
+      {% endif %}
+
+      {% if show.venue %}
+         {% if show.venue.url %}
+            <a href="{{ show.venue.url }}" target="_blank">{{ show.venue.name }}</a>,
+         {% else %}
+            {{ show.venue }},
+         {% endif %}
+         {% if show.venue.address %}
+            {{ show.venue.address }}, 
+         {% endif %}
+         {% if show.venue.city.state %}
+            {{ show.venue.city.name }}, {{ show.venue.city.state.name }}
+         {% else %}
+            {{ show.venue.city.name }}
+         {% endif %}
+         {% ifnotequal show.venue.city.country.name "USA" %}
+            {{ show.venue.city.country.name }}
+         {% endifnotequal %}
+         <br />
+         {% if show.venue.phone %}
+            {{ show.venue.phone }}
+            <br />
+         {% endif %}
+      {% endif %}
+
+      {% if show.bands_ %}
+         With:
+         {% for band in show.bands_ %}
+            {% if band.url %}
+               <a href="{{ band.url }}" target="_blank">{{ band.name }}</a>
+            {% else %}
+               {{ band.name }}
+            {% endif %}
+            {% if not forloop.last %}
+               &bull;
+            {% endif %}
+         {% endfor %}
+         <br />
+      {% endif %}
+
+      {% if show.notes %}
+         {{ show.notes|safe }}
+      {% endif %}
+      </p>
+   {% endfor %}
+{% else %}
+None at this time.
+{% endif %}
+<br clear="all" />
+
+{% if flyer_gigs %}
+<div class="thumb-box">
+   <h2>Flyers</h2>
+   <div style="width:90%; margin-left:auto;">
+   {% for gig in flyer_gigs %}
+      <div style="display:inline-table;">
+      <table class="image-table">
+         <caption>{{ gig.venue.name}}, {{ gig.date|date:"F 'y" }}</caption>
+         <tr><td>
+         <a href="{{ gig.flyer.image.url }}" class="fancybox" rel="madeira-gallery">
+            <img src="{{ gig.flyer.get_thumbnail_url }}" alt="{{ gig.date|date:"F d, Y" }}" title="{{ gig.date|date:"F d, Y" }}" /></a>
+         </td></tr>
+      </table>
+      </div>
+   {% endfor %}
+   </div>
+   <div clear="all"></div>
+   <center><p>To see all our flyers in full size, check out our <a href="{% url 'band.views.flyers' %}">show flyer gallery</a>.</p></center>
+</div>
+{% endif %}
+
+{% if previous %}
+   <h2>Previous Shows</h2>
+   <center>
+   <table border="0" cellpadding="3" cellspacing="3" width="95%">
+   <tr><th width="20%" align="center">Date</th><th width="40%" align="center">Venue</th><th width="40%" align="center">Bands</th></tr>
+   {% for show in previous %}
+      <tr>
+         <td width="20%">{{ show.date|date:"M d, Y" }}</td>
+         <td width="40%">
+            {% if show.title and show.url %}
+               <a href="{{ show.url }}" target="_blank">{{ show.title }}</a>,
+            {% else %}
+               {% if show.title %}
+                  {{ show.title }},
+               {% endif %}
+            {% endif %}
+            {% if show.venue.url %}
+               <a href="{{ show.venue.url }}" target="_blank">{{ show.venue.name }}</a>,
+            {% else %}
+               {{ show.venue.name }},
+            {% endif %}
+            {{ show.venue.city.name }}, {{ show.venue.city.state.abbrev }}
+            {% ifnotequal show.venue.city.country.name "USA" %}
+               {{ show.venue.city.country.name }}
+            {% endifnotequal %}
+         </td>
+         <td width="40%">
+            {% for band in show.bands_ %}
+               {% if band.url %}
+                  <a href="{{ band.url }}" target="_blank">{{ band.name }}</a>
+               {% else %}
+                  {{ band.name }}
+               {% endif %}
+               {% if not forloop.last %}
+                  &bull;
+               {% endif %}
+            {% endfor %}
+         </td>
+      </tr>
+   {% endfor %}
+   </table>
+   </center>
+{% endif %}
+
+{% if stats %}
+<h2>Past Show Statistics</h2>
+<table border="0" cellpadding="3" cellspacing="3">
+   <tr><th align="left">Number of shows:</th><td>{{ stats.count }}</td></tr>
+   <tr><th align="left">Number of unique venues:</th><td>{{ stats.venues }}</td></tr>
+   <tr><th align="left">Number of unique cities:</th><td>{{ stats.cities }}</td></tr>
+   <tr><th align="left">Number of unique states:</th><td>{{ stats.states }}</td></tr>
+   <tr><th align="left">Number of unique countries:</th><td>{{ stats.countries }}</td></tr>
+   <tr><th align="left">Number of unique bands:</th><td>{{ stats.bands }}</td></tr>
+</table>
+{% endif %}
+
+{% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/madeira/templates/gigs/upcoming_gigs_tag.html	Mon Mar 12 16:57:38 2012 -0500
@@ -0,0 +1,31 @@
+{% load url from future %}
+{% if gigs %}
+<div class="center-block">
+<h2>Upcoming Shows...</h2>
+ 
+<center><table border="0" cellspacing="10" cellpadding="3"><tr>
+{% for gig in gigs %}
+   {% if gig.flyer %}
+   <td>
+   <a href="{{ gig.flyer.image.url }}" class="fancybox" rel="madeira-gallery">
+      <img src="{{ gig.flyer.get_thumbnail_url }}" alt="{{ gig.flyer.caption }}" title="{{ gig.flyer.caption }}" /></a>
+   <br /><center>{{ gig.flyer.caption }}</center>
+   </td>
+   {% endif %}
+{% endfor %}
+</tr></table></center>
+
+<ul>
+{% for gig in gigs %}
+<li><strong>{{ gig.date|date:"l, F d" }}</strong>:
+{% if gig.venue %}
+   {{ gig.venue.name }}, {{ gig.venue.city.name }}{% if gig.venue.city.state %}, {{ gig.venue.city.state.name }}{% endif %} {% ifnotequal gig.venue.city.country.name "USA" %} {{ gig.venue.city.country.name }} {% endifnotequal %}
+{% else %}
+   Venue to be announced! Stay tuned!
+{% endif %}
+</li>
+{% endfor %}
+</ul>
+<center><a href="{% url 'gigs-index' %}">See all upcoming shows...</a></center>
+</div>
+{% endif %}
--- a/madeira/urls.py	Sun Mar 11 14:29:42 2012 -0500
+++ b/madeira/urls.py	Mon Mar 12 16:57:38 2012 -0500
@@ -1,4 +1,4 @@
-from django.conf.urls.defaults import *
+from django.conf.urls.defaults import patterns, include
 from django.contrib import admin
 from django.conf import settings
 
@@ -6,12 +6,8 @@
 
 urlpatterns = patterns('',
    (r'^', include('band.urls')),
+   (r'^gigs/', include('gigs.urls')),
    (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    (r'^admin/', include(admin.site.urls)),
    (r'^photologue/', include('photologue.urls')),
 )
-
-if settings.DEBUG:
-   urlpatterns += patterns('',
-      (r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
-   )