views:

395

answers:

8

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 list of all the Entities that displays 'name' if Team and 'firstname' and 'lastname' if Athlete.

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)
A: 

Loop over all the entities... if entity.class == 'Athlete' and entity.firstname and entity.lastname: blah

Hope this helps.

Edit: hmmm looks like I forgot about actually getting the combined list of both entities. Not sure I know of a slick way to do that.

Mikhail P
A: 

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

http://stackoverflow.com/questions/929029/how-do-i-access-the-child-classes-of-an-object-in-django-without-knowing-the-name

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.

Paul McMillan
A: 

I am not very clear what you want to do, but in any case you can add a criteria in dervied class instead of checking unicode method of derived classes

e.g. you can ask the class isTypeA ? or why don't you check the type?

Anurag Uniyal
+1  A: 

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.

David
A: 

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'
Thierry Lam
A: 

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.

Adam Dziendziel
A: 

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)
ieure
+1  A: 

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
zlovelady