Polymorphism in Django

前端 未结 8 906
死守一世寂寞
死守一世寂寞 2021-01-07 06:11

I have the following models. How do I get access to the unicode of the inheriting tables (Team and Athete) from the Entity table? I\'m trying to display a l

相关标签:
8条回答
  • 2021-01-07 06:49

    This is a little ugly, but I think it should work:

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

    Check out http://docs.djangoproject.com/en/1.0/topics/db/models/#id7 for more on multi-table inheritance. Just be careful, because the Django ORM is inevitably a leaky abstraction and things you might normally do with objects can get you in trouble, or do unexpected things.

    0 讨论(0)
  • 2021-01-07 06:56

    I answered a similar question a while ago. Have a look, I think one of the answers probably solves your problem as well.

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

    My answer from there was to add this to the parent 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)]
    

    Then you can call that function to get the children objects (in your case you will only have one) and then call the unicode function from that object.

    0 讨论(0)
  • 2021-01-07 06:58

    If I undestand correctly, you are simply asking how to call the __unicode__ method of a given object.

    Use unicode(instance) and depending on the type of entity, the appropriate implementation will be called polymorphically.

    0 讨论(0)
  • 2021-01-07 06:59

    I don't believe you have to do anything. If Entity is never instantiated directly, you will never call the non-existent Entity.__unicode__ method. However, if you'd like to play it save, you could add a stub method in your Entity class:

    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)
    

    You are now assured that any class which inherits from Entity will have a __unicode__ method, and you can simply traverse them:

    for thing in [TeamA(), AthleteA(), TeamB(), AthleteB()]:
        print unicode(thing)
    
    0 讨论(0)
  • 2021-01-07 07:07

    This answer from Carl Meyer to the question mentioned earlier by Paul McMillan might be what your looking for. A subtlety to this problem not captured in some of the answers is how to get at derived class instances from a QuerySet on Entity.

    The Problem

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

    A Solution

    Use the InheritanceCastModel mixin in the answer linked above as a base class for Entity. You can then cast from Entity instances to the actual derived class instances. This is particularly handy when you want to use querysets on your parent class (Entity) but access the derived class instances.

    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 讨论(0)
  • 2021-01-07 07:09

    From pure Python, you can use the isinstance function:

    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 讨论(0)
提交回复
热议问题