Django. Могу ли я создать глобальную переменную, к которой можно обращаться/манипулировать из разных функций в разных файлах?

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

Мой пример ниже. Обратите внимание, как я должен передать справочный словарь people_ref каждой функции деформации. Что я хотел бы сделать, так это установить какую-то глобальную переменную people_ref, к которой можно получить доступ из любого места. Таким образом, я мог бы просто сбросить ответ People.in_bulk() в глобальный пул, а затем получить к нему доступ непосредственно из функций деформации без необходимости передачи ссылки. Есть ли способ сделать это?

Что я хочу назвать:

>>> myapp.models.make_crazy_books([1,2,3])

Из myapp/models.py:

import itertools
from django.db import models
from myapp.utils import deform

class People(models.Model):
    born = model.DateField()

class Book(models.Model):
    author = models.ForeignKey(People, related_name='author_set')
    editor = models.ForeignKey(People, related_name='editor_set')
    last_edition = model.DateField()

def make_crazy_books(book_ids):
    book_list = Book.objects.using("db1").filter(id__in=book_ids) #Query here, db1

    people_list = ((b.author_id, b.editor_id) for b in book_list)
    people_ids = set(itertools.chain(*people_list))
    people_ref = People.objects.using("db2").in_bulk(people_ids) #Query here, db2

    #Would like to not have to send people_ref to each function
    book_list = deform.deform_edition(book_list, people_ref)
    book_list = deform.deform_author(book_list, people_ref)
    """ ... do some other deforming functions """

    return book_list

Из mayapp/utils/deform.py:

def deform_edition(book_list, people_ref):
    for book in book_list:
        author = people_ref[book.author_id] #Change to global lookup?
        b.last_edition = author.born
    return book_list

def deform_author(book_list, people_ref):
    for book in book_list:
        editor = people_ref[book.editor_id] #Change to global lookup?
        b.author = editor
    return book_list

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

РЕДАКТИРОВАТЬ: Возможно, кэширование в локальной памяти будет работать, так как это потокобезопасно?


person user749618    schedule 09.05.2012    source источник
comment
Кэширование LocMem является потокобезопасным, но за счет производительности. В документации ясно сказано, что это не хороший выбор для производственных сред. Глобальные переменные — это всегда плохая идея, я считаю особенностью Python/Django то, что их использование не рекомендуется.   -  person Chris Pratt    schedule 09.05.2012


Ответы (1)


Как правило, совместное использование данных между группой связанных функций - это то, для чего предназначен ООП - определите класс, который содержит функции (как методы), затем создайте экземпляр класса с конкретными данными.

В этом случае, хотя с данными уже связан класс — это объекты QuerySet of People. Таким образом, вы можете определить собственный подкласс QuerySet для People, который содержит методы deform — к сожалению, в Django, чтобы заставить его работать, вам также необходимо определить собственный менеджер, переопределяющий get_query_set, чтобы вернуть ваш подкласс QuerySet.

person Daniel Roseman    schedule 09.05.2012