django: How to get model class from model name

How do you get the model class object from a string containing model name?

This came up multiple times during SeenReport development. While recording views, saving votes and adding comment on an object, I had to get the model class using the model name. The scenario would be,

  • The view receives the model name and object id
  • Fetch the object from db
  • Perform action on the object

However, I couldn’t find a suitable way to get model class from the model name. The best way I could find was by using the globals function. Here is how it worked,

def my_view(request, model_name, object_id):
      model_class = globals()[model_name]
      obj = get_object_or_404(model_class, id=object_id)
      # perform required actions and return response

However, using globals requires that the models should already be imported. This would fail for a model that didn’t exist in global scope. Also I had to needlessly import models in views.

My guess was that there should be solution in the content types framework. After poking around for a while I found ContentType.model_class. This is how the above code would look like,

def my_view(request, model_name, object_id):
      model_class = ContentType.objects.get(model=model_name).model_class()
      obj = get_object_or_404(model_class, id=object_id)
      # perform required actions and return response

Related posts:

  1. django: Hacking django object_list to take list of templates
  2. django: How to expire session on browser close

3 Comments

  1. Farhan Ahmad says:

    Pretty cool. I love the content types framework, it has saved me time in the past.

  2. Evgeny Sizikov says:

    If you’re using the Django ContentTypes you’ll be getting a database hit during each model name resolution.

    It would be better to use Django API for the task:
    {{{
    from django.db.models import get_model

    # app_name should contain the model’s application name in lower case
    # Example: app_name = “myfirstapp”
    # Note: model name is case-insensitive
    model = get_model(app_name, “MyCoolModel”)
    }}}

  3. Adil Saleem says:

    Evgeny,

    You are quite right and the suggested fix will definitely solve this performance issue…thanks :)

Leave a Reply