我有一个主Event
类和四种事件类型。它们中的每一个都是(至少)的子类Event
。在事件的详细信息页面上,我正在为给定事件添加返回到管理界面的链接,以节省在管理中搜索的时间。不幸的是,无论子类如何,事件都是从父Event
类中选择的。我对这个问题的解决方案是鸭式,在这种情况下我觉得这绝对是糟糕的。我希望有一个更优雅且易于维护的解决方案来解决我的问题。
模型:
class Event(models.Model):
...
class ListedEvent(Event):
....
class RSVPEvent(Event):
....
class TicketedEvent(Event):
....
class TicketedConcert(TicketedEvent):
....
要查看事件详细信息,URL 会传递一个场地 slug 和事件名称 slug。这足以Event
在所有子事件中将单个事件与父模型隔离。它还让我将事件类型排除在 URL 之外,使它们更简单、更友好。
@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}
在我回过头来意识到我正在使用父Event
模型之前,假设我从其实际模型(父类的属性)中选择一个事件,这个解决方案更加优雅并且在 shell 中运行良好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,))
我当前的解决方案(父类的属性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
必须有一种更简单、更易于维护的方法来找出我正在查看的事件类型。有任何想法吗?