我有一个主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中工作得很好,假设我从其实际模型中选择一个事件(父类的属性{{ 1}}):
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
必须有一种更简单,更易于维护的方法来找出我正在查看的事件类型。有什么想法吗?
答案 0 :(得分:2)
这是a common issue,似乎仍然是Django的丑陋小鸭之一。
你至少可以重新安排2美分的DRY收益:
from django.core.exceptions import ObjectDoesNotExist
@property
def event_type(self):
for et in ('ticketedevent', 'rsvpevent', 'sillyhatsonlyevent', ...):
try:
getattr(self, et)
return et
except ObjectDoesNotExist:
pass
@property
def admin_link(self):
return reverse('admin:events_%s_change' % self.event_type, args=(self.id,))
如果您真的想要花哨,可以使用Event.__subclasses__
并生成事件类型列表。