开发者

Call method dynamically if it exists in Django

开发者 https://www.devze.com 2023-02-14 04:36 出处:网络
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.

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 application开发者_JAVA技巧s (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


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
        searchables.append(searchable)
    else:
        # 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
search.register_search_engine(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)
       search_results.append(do_search(search_string))
    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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消