I have a main Event
class, and four event types. Each of them is a subclass of (at least) Event
. On an event's detail page, I am adding a link back to the admin interface for a given event to save the time of searching in the admin. Unfortunately, regardless of child class, the events are selected from the parent Event
class. My solution to this problem was to duck type, which I find to be absolutely awful in this instance. I am hoping there is a more elegant and easy-to-maintain solution to my problem.
Model:
class Event(models.Model):
...
class ListedEvent(Event):
....
class RSVPEvent(Event):
....
class TicketedEvent(Event):
....
class TicketedConcert(TicketedEvent):
....
To see event details, the URL passes a venue slug and event name slug. This is enough info to isolate a single event from the parent Event
model across all the child events. It also lets me keep the event type out of the URL, making them simpler and more friendly.
@render_to('events/event_details.html')
def event_details(request, venue, slug):
"""
Detail view of an event.
"""
try:
event = Event.objects.select_related(
'listedevent',
'rsvpevent',
'ticketedevent',
'ticketedconcert',
'venue',
'sites',
'dj',
).get(
slug=slug,
venue__slug=venue,
)
except Event.DoesNotExist:
raise Http404
return {'event': event}
Before I went back and realized that I was using the parent Event
model, this solution was much more elegant and worked fine in the shell assuming I select an event from its actual model (property of parent class Event
):
@property
def admin_link(self):
et = self.__class__.__name__.lower()
# ALWAYS: et == 'event', reverse() fails, returns ''
return reverse('admin:events_%s_change' % et, args=(self.id,))
My current solution (property of parent class Event
):
@property
def admin_link(self):
duck = None
try:
duck = self.ticketedevent.ticketedconcert.artist_name
return reverse(
'admin:events_ticketedconcert_change',
args=(self.id,)
)
except:
pass
try:
duck = self.ticketedevent.max_tickets
return reverse(
'admin:events_ticketedevent_change',
args=(self.id,)
)
except:
pass
try:
duck = self.rsvpevent.total_rsvp
return reverse(
'admin:events_rsvpevent_change',
args=(self.id,)
)
except:
pass
try:
duck = self.listedevent.name
return reverse(
'admin:events_listedevent_change',
args=(self.id,)
)
except:
pass
There has to be a simpler, more easy-to-maintain method of finding out which type of event I'm looking at. Any ideas?