views:

153

answers:

2

When I have a given django model class like this:

class BaseClass(models.Model):
     some_field = models.CharField(max_length = 80)
     ...

and some subclasses of it, for example

class SomeClass(BaseClass):
     other_field =  models.CharField(max_length = 80)

Then I know I can get the derived object by calling

base  = BaseClass.objects.get(pk=3)
my_obj= base.someclass

Now the problem arises that I have multiple subclasses, and all I have is an instance of the base class. How can I get to the subclassed object without knowing it's class in advance?


The idea is to load a corresponding view and let that do the stuff. My project features only have a limited set of default actions for these models, like view, edit, delete etc. What I don't want is to expose the type of the given object via URL, so the "normal way" is not available

+2  A: 

How can I get to the subclassed object without knowing it's class in advance?

Why would this be useful? If you don't know what class you want, you also won't know which methods to call or which attributes can be inspected.


The idea is to load a corresponding view and let that do the stuff. My project features only have a limited set of default actions for these models, like view, edit, delete etc. What I don't want is to expose the type of the given object via URL, so the "normal way" is not available

If you know the set of model subclasses ahead of time, or are willing to register them with a central view list, you can do something like this:

VIEWS = [('subclass_a', a_views), ('subclass_b', b_views)]

def edit(request):
    base = (get base somehow)

    for attrname, views in VIEWS:
        if getattr(base, attrname) is not None:
            return views['edit']

Depending on how many different kinds of views you have, you might abstract the search out into a separate function, so the end view is something like:

def edit(request):
    return generic_base_view(request, 'edit')
John Millikin
Heh.. Almost thought this would come up. The idea is to load a corresponding view and let that do the stuff. My project features only have a limited set of default actions for these models, like view, edit, delete etc. What I don't want is to expose the type of the given object via URL, so the "normal way" is not available
Dave Vogt
Added your reply to the question, so others can see it more easily.
John Millikin
Thanks for the idea.. unfortunately this would complicate the app design too much :(
Dave Vogt
Your app's design is already complicated, else what you're trying to do would not be needed.
John Millikin
+3  A: 

There isn't a built-in way.

Perhaps the best thing to do is to define a derived_type field on your base class, which is set automatically on save of the derived class. You could then have a get_derived method on the base which checks the value of derived_type and returns the actual derived object.

Daniel Roseman
This is how I've handled it in the past. Be careful though; the derived_type field should really only be set on the initial save (when you know you're saving the subtype), and never changed thereafter. Otherwise it's easy to load up the instance as an instance of BaseClass, save it - and your derived_type field now thinks it is a BaseClass.
Carl Meyer