2012-10-03 94 views
0

我有一個主Event類,和四個事件類型。它們中的每一個都是(至少)Event的一個子類。在事件的詳細信息頁面上,我正在爲給定事件添加一個鏈接回管理界面,以節省在管理員中搜索的時間。不幸的是,無論孩子是什麼類別,這些事件都是從父母Event中選出的。我對這個問題的解決方案是鴨式,在這種情況下我覺得這是非常糟糕的。 我希望有一個更優雅和易於維護的解決方案來解決我的問題。如何知道通過父類選擇Django模型對象時哪個子類?

型號:

class Event(models.Model): 
    ... 

class ListedEvent(Event): 
    .... 

class RSVPEvent(Event): 
    .... 

class TicketedEvent(Event): 
    .... 

class TicketedConcert(TicketedEvent): 
    .... 

要查看活動詳情,網址通過場地蛞蝓和事件名稱蛞蝓。這是足夠的信息來隔離所有兒童事件中父母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模型,該解決方案是更優雅,並在外殼假設我選擇它的實際模型的事件(父類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 

@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的屬性)必須有一個更簡單,更易於維護的方法來找出我正在查看的事件類型。有任何想法嗎?

回答

2

這是acommonissue仍然似乎是Django的醜小鴨之一。

你至少可以用於幹增益2美分重新排列:

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__和產生的事件類型的列表。

相關問題