2013-05-19 3 views
5

Я ищу способ иметь глобальную переменную, доступную любому модулю в моем запросе django, без необходимости передавать его в качестве параметра. Традиционно в других MVC я бы сохранил его в контексте запроса или сеансе и получил доступ к контексту с помощью чего-то вроде метода get_current_context (которого я не смог найти в Django).Есть ли способ получить доступ к контексту извне в Django?

Есть ли что-то вроде этого или какой-либо другой механизм, который позволит мне иметь доступную ценность в любом месте контекста запроса?

TIA!

ОБНОВЛЕНИЕ: Мое исследование только придумало одно жизнеспособное решение - местные жители (некоторые утверждают, что это нежизнеспособно, но есть довольно активные дискуссии об этом, с плюсами и минусами, и похоже, что большинство людей думает, что вы должны быть в состоянии использовать его в Django, если вы это ответственно ответите).

+0

Возможно, но помните, что вы можете иметь несколько контекстов для каждого запроса и несколько потоков (= несколько запросов), работающих параллельно, что может привести к сотням активных контекстов в любой момент времени, и как бы он знал, какой контекст вернуться? – Aya

+0

Я не уверен, что понимаю ваш вопрос. Я говорю о возможности доступа к чему-то вроде сеанса из любого места в коде (без необходимости передавать переменную сеанса). –

+0

Ну, по «контексту» я предположил, что вы имели в виду объект 'django.template.Context' или его подкласс, который вы позже использовали для визуализации' django.template.Template'. Если это так, для каждого запроса может быть несколько объектов Context, если вы выполняете несколько объектов Template. если вы используете пользовательские теги шаблонов. Если вы используете один из встроенных в Django представлений типа «TemplateView», то большая часть этого процесса скрыта от вас. Это может помочь прояснить с помощью кода пример того, чего вы хотите достичь. – Aya

ответ

8

Мне все еще не совсем ясно, чего вы пытаетесь достичь, но похоже, что вам может понадобиться что-то вроде следующего.

Если вы создаете кусок промежуточного ПО, скажем ...

myproject/myapp/middleware/globalrequestmiddleware.py 

... который выглядит следующим образом ...

import thread 

class GlobalRequestMiddleware(object): 
    _threadmap = {} 

    @classmethod 
    def get_current_request(cls): 
     return cls._threadmap[thread.get_ident()] 

    def process_request(self, request): 
     self._threadmap[thread.get_ident()] = request 

    def process_exception(self, request, exception): 
     try: 
      del self._threadmap[thread.get_ident()] 
     except KeyError: 
      pass 

    def process_response(self, request, response): 
     try: 
      del self._threadmap[thread.get_ident()] 
     except KeyError: 
      pass 
     return response 

... а затем добавить его в свой settings.pyMIDDLEWARE_CLASSES в качестве первого элемента в списке ...

MIDDLEWARE_CLASSES = (
    'myproject.myapp.middleware.globalrequestmiddleware.GlobalRequestMiddleware', 
    # ... 
) 

... тогда вы можете использовать его в любом месте в процессе запроса/ответа, например ...

from myproject.myapp.middleware.globalrequestmiddleware import GlobalRequestMiddleware 

# Get the current request object for this thread 
request = GlobalRequestMiddleware.get_current_request() 

# Access some of its attributes 
print 'The current value of session variable "foo" is "%s"' % request.SESSION['foo'] 
print 'The current user is "%s"' % request.user.username 

# Add something to it, which we can use later on 
request.some_new_attr = 'some_new_value' 

... или что бы вы там ни хотели.

+0

Yep - Я искал что-то в этом направлении. –

+0

@EtaiRaz Хорошо. Я думаю, вам удалось смутить многих людей, используя фразу «контекст запроса», который обычно имеет [различное значение] (https://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing- context-requestcontext) в Django. – Aya

+0

Этот ответ shoud имеет намного больше, чем это. Это действительно помогает, когда код становится сложным и разветвленным - и тогда вам вдруг придется использовать запрос на что-то совершенно другое – velis

3

Вы должны написать свой собственный ContextProcessor, как описано here.


EDIT:

После того как вы создали Контекстный процессор, например,

def ip_address_processor(request): 
    return {'ip_address': request.META['REMOTE_ADDR']} 

вы можете получить переменные, необходимые при инициализации RequestContext, как это:

from django.template import RequestContext 

def myview(request): 
    rc = RequestContext(request) 
    rc.get('ip_address') 

Однако обратите внимание, что если вы не поместите свой Контекстный процессор в TEMPLATE_CONTEXT_PROCES SORS кортеж, вы должны передать процессор в RequestContext в качестве аргумента, например:

from django.template import RequestContext 

def ip_address_processor(request): 
    return {'ip_address': request.META['REMOTE_ADDR']} 

def myview(request): 
    rc = RequestContext(request, processors=[ip_address_processor]) 
    rc.get('ip_address') 

Некоторые полезные ссылки:

+0

Я не уверен, что понимаю, как это позволит мне иметь переменную, доступную из любого места в коде (любой контроллер, любая внутренняя библиотека и т. Д.) –

+0

Я отредактировал ответ :) – Markon

+1

Похоже на это например, вы фактически передаете запрос в качестве параметра, чтобы получить контекст. На самом деле это то, чего я пытаюсь избежать. До сих пор использование локаторов потоков, похоже, дает ответ на этот вопрос (хотя некоторые утверждают, что это не рекомендуется) –

1

You все равно можно получить доступ к текущей сессии в любом месте.

Использование:

from django.contrib.sessions.backends.db import SessionStore 

... 
s = SessionStore() 
s.session_key # unique_id 
s['myvar'] = "something" 
s.save() 

Это, конечно, использует базу данных и таблицу сессий, так что может быть немного слишком много накладных расходов. Является ли переменная зависящей от сеанса, или это просто глобальная стоимость?

Docs: https://docs.djangoproject.com/en/dev/topics/http/sessions/#using-sessions-out-of-views

P.S. То, что я делал в прошлом, создало мою собственную таблицу с помощью столбца session_id и других вещей, а затем сделало SQL для выбора данных на основе session_id вручную. Гораздо быстрее, чем использовать саундтрек SessionStore()

+0

Это выглядит хорошо, если оно работает, но почему это означает, что я должен хранить сеанс в базе данных? Не могу ли я использовать для этого локальное пространство памяти или memcached? –

+0

Хорошо, вам не нужно использовать базу данных, если вы используете что-то вроде memcached. Он должен хорошо работать с этим (у меня нет memcached, настроенного на моих серверах, поэтому он полностью забыл об этом для непостоянного хранения) – Patrick

Смежные вопросы