2009-09-09 12 views
1

我有以下型號。我如何從Entity表中訪問繼承表(Team和Athete)的unicode?我試圖顯示所有顯示'姓名'的實體的列表,如果團隊和'名字'和'姓氏'如果運動員。Django中的多態性

class Entity(models.Model): 
    entity_type_list = (('T', 'Team'), ('A', 'Athlete')) 
    type = models.CharField(max_length=2, choices=entity_type_list,default='P') 
    pictureurl = models.URLField('Picture Url', verify_exists=False, max_length=255, null=True, blank=True) 


class Team(Entity): 

    name = models.CharField(max_length=100) 

    def __unicode__(self): 
    return self.name 

class Athlete(Entity): 

    firstname = models.CharField(max_length=100) 
    lastname = models.CharField(max_length=100) 

    def __unicode__(self): 
    return '%s %s' % (self.firstname, self.lastname) 
+0

你能解釋一下你確切想要什麼嗎?例如做什麼類型的方法你想添加到實體? – 2009-09-09 04:59:56

回答

5

answer from Carl Meyer由保羅·麥克米蘭前面提到的問題可能是你在找什麼。在某些答案中沒有捕捉到這個問題的一個微妙之處,那就是如何從實體上的QuerySet獲取派生類實例。

的問題

for entity in Entity.objects.all() 
    print unicode(entity) # Calls the Entity class unicode, which is not what you want. 

解法

使用InheritanceCastModel混入在上面鏈接作爲實體基類答案。然後,您可以從Entity實例轉換爲實際的派生類實例。當你想在父類(實體)上使用查詢集但訪問派生類實例時,這一點特別方便。

class Entity(InheritanceCastModel): 
    # your model definition. You can get rid of the entity_type_list and type, as the 
    # real_type provided by InheritanceCastModel provides this info 

class Athlete(Entity): 
    # unchanged 

class Team(Entity): 
    # unchanged 

for entity in Entity.objects.all(): 
    actual_entity = entity.cast() 
    print unicode(actual_entity) # actual entity is a a Team or Athlete 
+0

還有另一種內置解決方案,用於[使您的模型變形](https://django-polymorphic.readthedocs.org/en/latest/quickstart.html#making-your-models-polymorphic),並且該應用程序處於[github上](https://github.com/chrisglass/django_polymorphic) – chaim 2014-07-28 10:42:36

0

在所有實體上循環...如果實體。 class =='Athlete'and entity.firstname and entity.lastname:blah

希望這會有所幫助。

編輯:嗯看起來像我忘了實際得到兩個實體的組合列表。不知道我知道一個很好的方法來做到這一點。

0

我剛纔回答了一個類似的問題。看看,我認爲其中一個答案可能也解決了你的問題。

How do I access the child classes of an object in django without knowing the name of the child class?

我的回答有把它添加到父類:

def get_children(self): 
    rel_objs = self._meta.get_all_related_objects() 
    return [getattr(self, x.get_accessor_name()) for x in rel_objs if x.model != type(self)] 

然後你就可以調用該函數來獲取子對象(在你的情況下,你只能有一個)然後從該對象調用unicode函數。

0

我不是很清楚,你想做的事,但在任何情況下,你可以在dervied類添加的不是檢查unicode的派生類

如的方法的標準你可以問班級isTypeA?或者你爲什麼不檢查類型?

0

這是有點醜,但我認爲它應該工作:

entities = Entity.objects.all() 
for entity in entities: 
    try: 
     print entity.team 
    except: 
     print entity.athlete 

退房http://docs.djangoproject.com/en/1.0/topics/db/models/#id7以獲得更多關於多表繼承。要小心,因爲Django ORM不可避免地是一個漏洞抽象,而且你可能通常用對象做的事情會讓你陷入困境,或者做出意想不到的事情。

1

從純Python,你可以使用isinstance功能:

class Entity: 
    def __init__(self): 
     if isinstance(self, Team): 
      print 'is team' 
     elif isinstance(self, Athlete): 
      print 'is athlete' 

class Team(Entity): 
    def __unicode__(self): 
     return 'Team' 

class Athlete(Entity): 
    def __unicode__(self): 
     return 'Athlete' 
0

如果我正確地已瞭解,你只是問如何調用給定對象的__unicode__方法。

使用unicode(instance)並根據實體的類型,相應的執行將被稱爲多態。

0

我不相信你必須做任何事情。如果Entity從未直接實例化,則永遠不會調用不存在的Entity.__unicode__方法。但是,如果你想發揮它的保存,你可以在你的Entity類添加一個存根方法:

class Entity(models.Model): 

    def __unicode__(self): 
     pass 

class Team(Entity): 

    def __unicode__(self): 
     return self.name 

class Athlete(Entity): 

    def __unicode__(self): 
     return '%s %s' % (self.firstname, self.lastname) 

你現在放心,從Entity繼承的任何類將有一個__unicode__方法,你可以簡單地遍歷他們:

for thing in [TeamA(), AthleteA(), TeamB(), AthleteB()]: 
    print unicode(thing)