3

I'm currently writing a Django template template tag, and I would like to be able to reference a class in it with a string, just like in settings.MIDDLEWARE_CLASSES, for example. The tag would look like {% mytag "myproject.lib.mymodule.SomeClass" %}.

The question is fairly simple : in my template tag, how may I easily resolve this string to the actual referenced class?

Thanks.

Pierre
  • 6,084
  • 5
  • 32
  • 52
  • The answer is "yes". Now. Please edit the question to ask what you **really** what to know, which is "how do I transform a class name into a class object." Then we can ask "Why are you trying to do this?" Often, you'd be happier with some other technique. Please explain what your tag will do with the class object named as an argument. – S.Lott Feb 08 '12 at 21:22
  • I'd be interested in seeing how this is done, regardless of whether it's the best way of doing things or not – Timmy O'Mahony Feb 08 '12 at 21:34
  • Thanks. The question was purely technical, and could be useful in many places, not necessarily in a template tag. But if you are curious, the goal is to create something similar to [Facebook's BigPipe](http://www.facebook.com/notes/facebook-engineering/bigpipe-pipelining-web-pages-for-high-performance/389414033919). The tag will take a Pagelet class path as argument, register it for deferred rendering, and finally return the placeholder, if necessary. – Pierre Feb 08 '12 at 21:46

2 Answers2

1

Django has some utility functions for handling this situation.

In Django 1.7 or higher, use django.utils.module_loading.import_string function.

In Django 1.6, use django.utils.module_loading.import_by_path function.

(It looks like import_by_path exists in 1.5 as well, although it's not documented)

Example usage:

from django.utils.module_loading import import_string

my_class = import_string('myproject.lib.mymodule.SomeClass')
Pwnosaurus
  • 2,058
  • 1
  • 19
  • 21
1

If you really need to import a package specified as a string, you will need to check out the __import__ function.

Basic usage is that you can attempt to import the package specified in the string like

my_class = __import__("myproject.lib.mymodule.SomeClass")

which is equivalent to

import myproject.lib.mymodule.SomeClass as my_class

However, as S.Lott mentioned, you'll need to consider carefully if that's really the best way to solve the problem.

Michael C. O'Connor
  • 9,742
  • 3
  • 37
  • 49
  • Thanks ! I considered many other options, but this one really seems to be the most flexible. – Pierre Feb 08 '12 at 22:00
  • Just to add that the solution doesn't actually work as is, and I needed a little rsplit magic, and the `fromlist` argument of the `__import__` function. I actually read [this question](http://stackoverflow.com/questions/547829/how-to-dynamically-load-a-python-class) to find the right answer. – Pierre Feb 08 '12 at 23:30