Take the 2-minute tour ×

I'm creating website based on Django (I know it's pure Python, so maybe it could be also answered by people who knows Python well) and I need to call some methods dynamically.

For example I have few applications (modules) in my website with the method "do_search()" in the views.py. Then I have one module called for example "search" and there I want to have an action which will be able to call all the existing "do_search()" in other applications. Of course I don't like to add each application to the import, then call it directly. I need some better way to do it dynamically.

I can read INSTALLED_APPS variable from settings and somehow run through all of the installed apps and look for the specific method? Piece of code will help here a lot :)

Thanks in advance! Ignas

share|improve this question
i don't think what you are doing is recommended way of doing it . –  Bunny Rabbit Feb 27 '11 at 9:19
and what is the recommended way then? If I'm doing wrong, I'm always want to learn to do things right :) –  Ignas Butėnas Feb 27 '11 at 9:30
This is really a comment, not an answer to the question. Please use "add comment" to leave feedback for the author. –  Dominic Kexel Aug 15 '12 at 13:42
add comment

2 Answers

up vote 3 down vote accepted

I'm not sure if I truly understand the question, but please clarify in a comment to my answer if I'm off.

# search.py
searchables = []

def search(search_string):
    return [s.do_search(search_string) for s in searchables]

def register_search_engine(searchable):
    if hasattr(searchable, 'do_search'):
        # you want to see if this is callable also
        # raise some error perhaps

# views.py
def do_search(search_string):
    # search somehow, and return result

# models.py

# you need to ensure this method runs before any attempt at searching can begin
# like in models.py if this app is within installed_apps. the reason being that
# this module may not have been imported before the call to search.
import search
from views import do_search

As for where to register your search engine, there is some sort of helpful documentation in the signals docs for django which relates to this.

You can put signal handling and registration code anywhere you like. However, you'll need to make sure that the module it's in gets imported early on so that the signal handling gets registered before any signals need to be sent. This makes your app's models.py a good place to put registration of signal handlers.

So your models.py file should be a good place to register your search engine.

Alternative answer that I just thought of:

In your settings.py, you can have a setting that declares all your search functions. Like so:

# settings.py
SEARCH_ENGINES = ('app1.views.do_search', 'app2.views.do_search')

# search.py
from django.conf import settings
from django.utils import importlib

def search(search_string):
    search_results = []
    for engine in settings.SEARCH_ENGINES
       i = engine.rfind('.')
       module, attr = engine[:i], engine[i+1:]
       mod = importlib.import_module(module)
       do_search = getattr(mod, attr)
    return search_results

This works somewhat similar to registering MIDDLEWARE_CLASSES and TEMPLATE_CONTEXT_PROCESSORS. The above is all untested code, but if you look around the django source, you should be able to flesh this out and remove any errors.

share|improve this answer
Looks really cool. But some questions: - It is worth to create a static class in search.py, to keep all the registered modules? I'm not sure when this object will go away... In production I'm using apache, of course not the django's webserver and it is interesting when objects are deleted? For one user the session will be kept and another one will get the new object, right? - So in general when the model will be called, it will get some signal and then will try to register the searchable object, right? –  Ignas Butėnas Feb 27 '11 at 8:35
As far as I'm aware, the objects lifetime is that of the request/response phase. If you're using WSGI interface, I'm fairly confident that each request has its own sandbox to execute in. Someone else can correct me if I'm wrong - or a quick google search should yield the answer. No need for a class though, this method will work fine. Perhaps a check to make sure that the searchable only registers itself once would be a good idea. –  Josh Smeaton Feb 27 '11 at 8:41
Thanks! About the last point - sure :) Time to read about signals! Thanks one more time for the help! –  Ignas Butėnas Feb 27 '11 at 8:45
@Neoman Signals won't help you too much I think. I only took the idea of when to register the signals as an example for this case. Look at my edit that describes an alternative method. I think that will be more reliable. It also means that you don't have to have your app with the do_search function within your INSTALLED_APPS. –  Josh Smeaton Feb 27 '11 at 8:55
Cool! Earlier I've also dug something about importlib, so I guess this alternative answer you've posted will be solution for my problem. Thanks! –  Ignas Butėnas Feb 27 '11 at 9:12
show 1 more comment

If you can import the other applications through

import other_app

then it should be possible to perform

 method = getattr(other_app, 'do_' + method_name)
    result = method()

However your approach is questionable.

share|improve this answer
add comment

Your Answer


