2016-10-06 3 views
13
나는 응용 프로그램 기본값 및 오해하기 어려운, 사용하기 쉬운, 그리고 약간의 오버 헤드가 설정을 가질 수있는 방법을 찾고 있어요

..장고 앱의 기본값은 무엇입니까?

현재

나는 그것이로 조직 한은 다음과 같습니다

myapp/defaults.py 
    # application defaults 
    import sys 
    if sys.platform == 'win32': 
     MYAPP_HOME_ROOT = os.path.dirname(os.environ['USERPROFILE']) 
    else: 
     MYAPP_HOME_ROOT = '/home' 
내 프로젝트에

나는이 : 내가 가져 정규 장고 방법 (from django.conf import settingssettings.XXX)의 설정을 사용할 수있는이 설정으로

mysite/settings.py 
    from myapp.defaults import *  # import all default from myapp 
    MYAPP_HOME_ROOT = '/export/home' # overriding myapp.defaults 

.

갱신-3 (이 필요한 이유)

  1. 기본 설정 ("기본값") :
    1. 응용 프로그램이 설정을 무시하여 구성 할 수있는 경우에 사용하는 것이 더 편리합니다 현명한 기본 설정이 있습니다.
    2. 응용 프로그램에 "도메인 지식"이 있으므로 가능할 때마다 적절한 기본값을 제공하는 것이 좋습니다.
    3. 모든 응용 프로그램에서 필요한 모든 설정을 응용 프로그램 사용자가 제공해야하는 경우 편리하지 않으므로 작은 하위 집합을 재정의하고 나머지는 기본값으로 두어도 충분합니다.
    4. 기본값은 환경에 반응 할 수있는 경우 유용합니다. 매우입니다. DEBUG이 True 일 때 다른 것을하고 싶지만 다른 모든 전역 설정이 유용 할 수 있습니다. MYAPP_IDENTICON_DIR = os.path.join(settings.MEDIA_ROOT, 'identicons') (https://en.wikipedia.org/wiki/Identicon)
    5. 프로젝트 (사이트/전역) 설정이 app-defaults를 덮어 써야합니다. 즉, 해당 사이트의 (글로벌) settings.py 파일에 MYAPP_IDENTICON_DIR = 's3://myappbucket.example.com/identicons'을 정의한 사용자가이 값을 받아야하며 응용 프로그램의 기본값이 아닙니다.
    6. 설정을 사용하는 일반적인 방법 (import .. settings; settings.FOO)에 가까운 솔루션은 새로운 구문이 필요한 솔루션보다 우수합니다 (새로운 구문이 다양해질 것이므로 앱에서 앱으로 설정을 사용하는 새롭고 독특한 방법을 얻을 수 있습니다).
    7. 파이썬의 선은 아마 여기에 적용 구현을 설명하기 어렵다
      • 경우, 그것은 나쁜 생각입니다.
      • 구현이 설명하기 쉬운 경우 좋은 생각 일 수 있습니다.

는 (원래 소식 명시되지 않은 상기 가정을두고, 아래의 두 가지 중요한 문제점을 상정 ..)

문제 # 1 :을가 앱 부 테스트를 실행할 때 그러나 사이트가 없기 때문에 settingsmyapp.defaults을 가지지 않습니다.

문제 # 2 : (즉 원형 가져올 것 때문에) 당신이 defaults.py에서 설정을 가져올 수 없기 때문에 myapp.defaults 요구, 설정에서 아무것도 (예를 들어 settings.DEBUG)를 사용하는 경우 큰 문제도 있습니다.

myapp/views.py 
    from .conf import conf as settings 
    ... 
    print settings.MYAPP_HOME_ROOT # will print '/export/home' when used from mysite 

이는 "빈"설정이 너무 파일로 작업 할 수있는 conf.py 파일을 허용하고 :

myapp/conf.py 
    from . import defaults 
    from django.conf import settings 

    class Conf(object): 
     def __getattr__(self, attr): 
      try: 
       return getattr(settings, attr) 
      except AttributeError: 
       return getattr(defaults, attr) 
    conf = Conf() # !<-- create Conf instance 

및 사용 :

는 문제 # 1를 해결하기 위해 나는 간접 레이어를 생성 myapp 코드는 익숙한 settings.XXX을 계속 사용할 수 있습니다.

문제 # 2를 해결하지 못하고 응용 프로그램 설정을 정의하지 못합니다. settings.DEBUG. 나의 현재 솔루션은 Conf 클래스에 추가하는 것입니다

from . import defaults 
    from django.conf import settings 

    class Conf(object): 
     def __getattr__(self, attr): 
      try: 
       return getattr(settings, attr) 
      except AttributeError: 
       return getattr(defaults, attr) 

     if settings.DEBUG: 
      MYAPP_HOME_ROOT = '/Users' 
     else: 
      MYAPP_HOME_ROOT = '/data/media' 
    conf = Conf() # !<-- create Conf instance 

하지만 내 사이트가 더 이상 설정을 무시할 수 있기 때문에이 만족하지 않고,/설정이 이제 두 개의 파일에 분산되어 myapp와의 기본값 ...

이 작업을 수행하는 더 쉬운 방법이 있습니까?

갱신-4 : "그냥 장고 테스트 러너를 사용 ..."

응용 프로그램을 사용하면 테스트 장고 프레임 워크에 의존 - 그리고 당신이 부트 스트랩해야한다는 사실을 주위에 얻을 수 없다 프레임 워크를 먼저 테스트해야합니다. 부트 스트랩 프로세스의 일부는 default settings.py를 생성하고 장고 제공 테스트 러너를 사용하여 실행될 가능성이있는 환경에서 앱을 테스트하고 있는지 확인하는 것입니다.

실제로 사실 인 것처럼 들리지만 실제로는 그렇지 않습니다. 기본값 인 settings.py (적어도 재사용 할 수있는 앱이 아님)은 없습니다. 통합 테스트에 대해 이야기 할 때 사이트/settings/apps/데이터베이스/캐시/리소스 제한/등으로 앱을 테스트하는 것이 좋습니다. 그것은 생산에서 마주 치게 될 것입니다. 그러나 단위 테스트의 경우 가능한 한 외부 종속성 (및 설정)을 최소화하면서보고있는 코드 단위 만 테스트하려고합니다. Django 테스트 주자는 프레임 워크의 주요 부분을 조롱하고해야하므로 "실제"환경에서 실행 중이라고 말할 수는 없습니다.

Django 테스트 러너는 훌륭하지만 처리 할 수없는 문제 목록이 많습니다. (i) 순차적으로 테스트를 실행하는 것이 너무 느려서 테스트 스위트가 사용되지 않게된다. (병렬로 실행될 때 < 5 분, 순차적으로 실행될 때 거의 1 시간) (ii) 때로는 테스트를 실행해야한다. 데이터베이스 (테스트를 실행할 수있는 테스트 데이터베이스에 어젯밤의 백업을 복원합니다. 조명기에 비해 너무 큽니다).

코, py.test, twill, Selenium 및 임의의 퍼지 테스트 도구를 만든 사람들은 실제로 테스트를 잘 알고 있습니다. 그들의 집단적 경험을 그릴 수없는 것은 수치 스러울 것입니다.

나는이 문제가 발생한 첫 번째 사람이 아니며 쉽고 일반적인 해결책이없는 것처럼 보입니다.

업데이트, 파이썬 OIDC-제공 방법 :

파이썬 - OIDC - 프로 바이더 패키지 ( https://github.com/juanifioren/django-oidc-provider)

이 앱 설정/기본값을 해결하기 위해 또 다른 창조적 인 방법이 여기에 다른 해결책을 가지고이 개 프로젝트는 문제.MyApp를이되고 내부 설정을 사용

from django.conf import settings 
class DefaultSettings(object): 
    @property 
    def MYAPP_HOME_ROOT(self): 
     return ... 

default_settings = DefaultSettings() 

def get(name): 
    value = None 
    try: 
     value = getattr(default_settings, name) 
     value = getattr(settings, name) 
    except AttributeError: 
     if value is None: 
      raise Exception("Missing setting: " + name) 

: 그것은 myapp/settings.py 파일에 기본값을 정의하는 속성을 사용

from myapp import settings 
print settings.get('MYAPP_HOME_ROOT') 

좋은 :이 문제 # 2 (기본값을 정의 할 때 설정을 사용)를 해결, 문제를 해결 # 1 (테스트의 기본 설정 사용).

나쁜 : 설정에 액세스하기위한 다른 구문 (일반 settings.FOOsettings.get('FOO'))의 MyApp는 (MyApp를에서 모든 기본값을 포함하지 않습니다 당신이 from django.conf import settings에서 얻을 설정) MyApp를 외부에 사용되는 설정에 대한 기본값을 제공 할 수 없습니다. (참고 : 관련이없는

갱신 2, 장고 - appconf 패키지가 ... 외부 코드는 일반 설정 및 MyApp를 기본값을 얻기 위해 from myapp import settings을 할 수 있지만 하나 이상의 응용 프로그램이 작업을 수행하고자 할 때 고장 당신은 아마 models.py에서 conf.py 파일을 가져와야합니다 그래서 장고의 appconfig가 ..) django-appconfig

은 응용 프로그램 설정은 초기로드해야하는 (myapp/conf.py에서 만든 -가) 초기로드 이후 :

from django.conf import settings 
from appconf import AppConf 
class MyAppConf(AppConf): 
    HOME_ROOT = '...' 

사용은 :

from myapp.conf import settings 
print settings.MYAPP_HOME_ROOT 

AppConf는 자동적으로 MYAPP_ 접두사를 추가하고 MYAPP_HOME_ROOT이 프로젝트의 설정에서 재정의/재정의 된 경우에도 자동적으로 감지합니다.

pro : 사용이 간편하고 문제 # 1 (테스트에서 앱 설정에 액세스) 및 문제 # 2 (기본값을 정의 할 때 설정 사용)를 해결합니다. conf.py 파일이 일찍로드되는 한 외부 코드는 myapp에 정의 된 기본값을 사용할 수 있어야합니다.

con : 상당히 마술입니다. conf.py의 설정 이름은 사용법과 다릅니다 (appconf가 자동으로 MYAPP_라는 접두사를 추가하기 때문에). Extenal/불투명 한 의존성.

+0

긴 토론이 아닌 질문으로 필터링 할 수없는 경우; 나는 당신의 질문이 "너무 광범위하게"폐쇄 될 수 있다는 것을 두려워합니다. 나는 이것을 [django bug tracker] (https://code.djangoproject.com)에서 사용하는 것이 좋습니다. –

+0

질문은 매우 간단합니다. "재사용 가능한 앱에서 어떻게 설정을 현명하게합니까?" 그 외 모든 것은 장난감 문제를 해결하는 솔루션이 충분하지 않은 이유와 모든 사람이 사용하는 분명한 해결책이없는 이유를 설명하기에 충분한 배경입니다. – thebjorn

+0

'class Conf' 솔루션 (canonical way, btw)을 사용할 때'myapp/defaults.py'에서'django.conf 가져 오기 설정 '을 할 수없는 이유는 무엇입니까? 모든 다른 솔루션 (하나와 첫 번째 제외) 나쁜 문서를 생성합니다, btw. – nitely

답변

3

방금 ​​모든 요구 사항을 기반으로 django-app-defaults을 만들었습니다. 이는 기본적으로 질문 (class Conf(object):)에 강조 표시된 두 번째 접근법을 일반화 한 것입니다.

사용법 :

from app_defaults import settings 

print(settings.MY_DEFAULT_SETTING) 
# yey 

# All `django.conf.settings` are also available 
print(settings.DEBUG) 
# True 

그냥 할 대신 애플 리케이션의 모든 하나의 응용 프로그램에 대한 기본 설정을로드하려면 : 그럼 어디서든 프로젝트 내에서

# my_app/defaults.py 

# `django.conf.settings` or any other module can be imported if needed 

# required 
DEFAULT_SETTINGS_MODULE = True 

# define default settings below 
MY_DEFAULT_SETTING = "yey" 

# Note: when apps or modules are explicitly passed, 
# the `DEFAULT_SETTINGS_MODULE` var is not required 

from app_defaults import Settings 

settings = Settings(apps=["my_app"]) 

# or 

from my_app import defaults 
settings = Settings(modules=[defaults]) 
+0

나는 그 접근법을 좋아한다. – thebjorn

2

문제 1 : 앱의 단위 테스트를 실행할 때 사이트가 없으므로 설정에 myapp.defaults가 없습니다.

이 문제가 당신을 위해 제대로 테스트 환경을 부트 스트랩으로 장고와 함께 제공되는 테스트 프레임 워크 (the documentation 참조)를 사용하여 해결된다. 테스트는 항상 DEBUG=False

문제 # 2 실행 장고 마음에

유지 : myapp.defaults는 설정에서 아무것도 사용할 필요가있는 경우 큰 문제도있다 (예를 들어 settings.DEBUG), 당신부터 설정을 defaults.py에서 가져올 수 없습니다 (순환 가져 오기이므로).

이것은 실제로 문제가되지 않습니다. 에서 myapp.settings으로 가져 오면 settings의 모든 항목이 범위에 포함됩니다. 따라서 DEBUG을 가져 오지 마십시오. 이미 글로벌 범위에서 사용할 수 있습니다.

+0

테스트 프레임 워크는'myapp.defaults import *'를 수행해야한다는 것을 어떻게 알 수 있습니까? 'myapp.settings'에/무엇이 있어야합니까? – thebjorn

+0

'manage.py'는 프로젝트/사이트에 속하고 일반 앱의 일부가 아니기 때문에 어떤 manage.py를 사용해야할지 잘 모르겠습니다. 재사용 가능한 응용 프로그램으로 프로젝트를 생성/배포해야합니까? 현재는'py.test'를 통해 app 테스트를 실행합니다. 종종'pytest-django' 패키지를 사용합니다. – thebjorn

+0

전체 _project_을 관리하는'manage.py'만이 있습니다. 앱에는 장고가 제공하는'manage.py' 파일이 없습니다. 이것은 앱에서'manage.py'라는 파일을 만드는 것을 멈추지는 않지만 의도하지 않은 부작용이있을 수 있습니다. –

2

django-pluggableappsettings이라는 앱 설정 관리를위한 장고 패키지를 작성했습니다.

설정에 적합한 기본 설정을 정의 할 수있는 패키지이지만 유형 확인 또는 호출 가능 설정과 같은 고급 기능도 추가되었습니다. 메타 설정을 사용하여 앱 설정을 쉽게 정의 할 수 있습니다. 물론 이것은 외부 의존성을 프로젝트에 추가합니다.

편집 한 다음과 같이

사용 예제가 될 수있다 :

이 핍를 사용하여 패키지를 설치합니다

pip install django-pluggableappsettings 

프로젝트의 파일 중 하나에 appSettings는 클래스를 만듭니다. 예 : 'app_settings.py'에 있습니다.

app_settings.py

from django_pluggableappsettings import AppSettings, Setting, IntSetting 

class MyAppSettings(AppSettings): 
    MY_SETTING = Setting('DEFAULT_VALUE') 
    # Checks for "MY_SETTING" in django.conf.settings and 
    # returns 'DEFAULT_VALUE' if it is not present 

    ANOTHER_SETTING = IntSetting(42, aliases=['OTHER_SETTING_NAME']) 
    # Checks for "ANOTHER_SETTING" or "OTHER_SETTING_NAME" in 
    # django.conf.settings and returns 42 if it is not present. 
    # also validates that the given value is of type int 

당신은 설정에 액세스하지 그래서 만약, 설정 만에 처음 액세스에 초기화되어 있는지, 어떤 파일에 MyAppSettings 가져 오기 및 그 속성

from mypackage.app_settings import MyAppSettings 
MyAppSettings.MY_SETTING 
MyAppSettings.ANOTHER_SETTING 

주에 액세스 django.conf.settings에 존재하지 않습니다.

관련 문제