Django @override_settings не позволяет словарь?

Я новичок в Python-декораторах, так что, возможно, мне не хватает чего-то простого, вот моя ситуация:

Это работает для меня:

def test_something(self):
    settings.SETTING_DICT['key'] = True #no error
    ...

Но это выдает "SyntaxError: ключевое слово не может быть выражением":

@override_settings(SETTING_DICT['key'] = True) #error
def test_something(self):
   ...

Просто чтобы прояснить, нормальное использование настроек переопределения работает:

@override_settings(SETTING_VAR = True) #no error
def test_something(self):
   ...

Есть ли способ использовать декоратор со словарем настроек или я что-то не так делаю?

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

1 ответ

Решение

Вы должны переопределить весь диктовку:

@override_settings(SETTING_DICT={'key': True})
def test_something(self):
   ...

Или вы можете использовать override_settings в качестве менеджера контекста:

def test_something(self):
     value = settings.SETTING_DICT
     value['key'] = True
     with override_settings(SETTING_DICT=value):
         ...

Начиная с Python 3.3 вы можете использовать collections.Chainmapесли вы хотите переопределить определенные значения в объекте dict (или другом сопоставлении) с помощью декоратора и сохранить код чистым из диспетчера контекста. https://docs.python.org/3/library/collections.html

from collections import ChainMap

@override_settings(SETTING_DICT=ChainMap({'key': 'value'}, settings.SETTING_DICT))
def test_something(self):
   ...

Вышеупомянутое не переопределит весь dict и все другие значения в SETTINGS_DICT будет доступно.

Для Python 2.7 вы можете использовать backport, который содержит Chainmapреализация. https://pypi.org/project/chainmap/

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

import copy
from django.conf import settings

settings_dict = deepcopy(settings.SETTINGS_DICT)
settings_dict['key1']['key2'] = 'new value'

@override_settings(SETTINGS_DICT=settings_dict)
def test_something(self):
    pass

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

Примечание: я пытался использовать settings.SETTINGS_DICT.copy() вместо deepcopy(settings.SETTINGS_DICT) но это, казалось, глобально переопределяет настройку для всех тестов...

Самое простое решение для меня (работает с python 3.6):

@override_settings(SETTINGS_DICT={**SETTINGS_DICT, 'yournewkey': yournewvalue})
Другие вопросы по тегам