Вызов метода динамически, если он существует в Django - PullRequest
1 голос
/ 27 февраля 2011

Я создаю веб-сайт на основе Django (я знаю, что это чистый Python, поэтому, возможно, на него могут ответить и люди, хорошо знающие Python), и мне нужно динамически вызывать некоторые методы.

Например, яНа моем сайте есть несколько приложений (модулей) с методом do_search () в views.py.Затем у меня есть один модуль, называемый, например, «поиск», и там я хочу иметь действие, которое сможет вызывать все существующие «do_search ()» в других приложениях.Конечно, я не люблю добавлять каждое приложение в импорт, а затем вызывать его напрямую.Мне нужен какой-то лучший способ сделать это динамически.

Я могу прочитать переменную INSTALLED_APPS из настроек и каким-то образом запустить все установленные приложения и найти конкретный метод?Кусок кода здесь очень поможет:)

Заранее спасибо!Игнас

Ответы [ 2 ]

3 голосов
/ 27 февраля 2011

Я не уверен, правильно ли я понимаю вопрос, но, пожалуйста, уточните в комментарии к моему ответу, если я не в курсе.

# 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)

Что касается того, где зарегистрировать вашу поисковую систему, в документах сигналов для django есть своего рода полезная документация, относящаяся к этому.

Вы можете разместить код обработки сигнала и регистрационный код где угодно. Однако вам необходимо убедиться, что модуль, в котором он находится, будет импортирован на ранней стадии, чтобы обработка сигналов была зарегистрирована до того, как какие-либо сигналы будут отправлены. Это делает models.py вашего приложения хорошим местом для регистрации обработчиков сигналов.

Так что ваш models.py файл должен быть хорошим местом для регистрации вашей поисковой системы.

Альтернативный ответ, о котором я только что подумал:

В вашем settings.py вы можете иметь настройку, которая объявляет все ваши функции поиска. Вот так:

# 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

Это работает примерно так же, как регистрация MIDDLEWARE_CLASSES и TEMPLATE_CONTEXT_PROCESSORS. Выше приведен весь непроверенный код, но если вы посмотрите на исходный код django, вы сможете уточнить это и устранить любые ошибки.

0 голосов
/ 27 февраля 2011

Если вы можете импортировать другие приложения через

import other_app

тогда должно быть возможно выполнить

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

Однако ваш подход сомнителен.

...