it-swarm.com.de

Wie verwalte ich lokale Einstellungen in Django?

Wie werden Einstellungen für die lokale Entwicklung und den Produktionsserver empfohlen? Einige von ihnen (wie Konstanten usw.) können in beiden geändert/abgerufen werden, aber einige von ihnen (wie Pfade zu statischen Dateien) müssen unterschiedlich bleiben und sollten daher nicht jedes Mal überschrieben werden, wenn der neue Code bereitgestellt wird.

Derzeit füge ich alle Konstanten zu settings.py hinzu. Jedes Mal, wenn ich einige Konstanten lokal ändere, muss ich sie auf den Produktionsserver kopieren und die Datei für produktionsspezifische Änderungen bearbeiten ... :( 

Bearbeiten: Anscheinend gibt es keine Standardantwort auf diese Frage. Ich habe die populärste Methode akzeptiert.

265
akv

In settings.py:

try:
    from local_settings import *
except ImportError as e:
    pass

Sie können überschreiben, was in local_settings.py benötigt wird. es sollte dann außerhalb Ihrer Versionskontrolle bleiben. Aber da du das Kopieren erwähnst, schätze ich, dass du keines verwendest;)

126
ohnoes

Zwei Scoops von Django: Best Practices für Django 1.5 schlägt vor, die Versionskontrolle für Ihre Einstellungsdateien zu verwenden und die Dateien in einem separaten Verzeichnis zu speichern:

project/
    app1/
    app2/
    project/
        __init__.py
        settings/
            __init__.py
            base.py
            local.py
            production.py
    manage.py

Die Datei base.py enthält allgemeine Einstellungen (z. B. MEDIA_ROOT oder ADMIN), während local.py und production.py ortsspezifische Einstellungen aufweisen:

In der Basisdatei settings/base.py:

INSTALLED_APPS = (
    # common apps...
)

In der lokalen Entwicklungseinstellungsdatei settings/local.py:

from project.settings.base import *

DEBUG = True
INSTALLED_APPS += (
    'debug_toolbar', # and other apps for local development
)

In der Dateiproduktions-Einstellungsdatei settings/production.py:

from project.settings.base import *

DEBUG = False
INSTALLED_APPS += (
    # other apps for production site
)

Wenn Sie dann Django ausführen, fügen Sie die Option --settings hinzu:

# Running Django for local development
$ ./manage.py runserver 0:8000 --settings=project.settings.local

# Running Django Shell on the production site
$ ./manage.py Shell --settings=project.settings.production

Die Autoren des Buches haben auch eine Mustervorlage für ein Projektlayout auf Github erstellt.

268
Rudolf Olah

Verwenden Sie anstelle von settings.py dieses Layout:

.
└── settings/
    ├── __init__.py  <= not versioned
    ├── common.py
    ├── dev.py
    └── prod.py

common.py ist der Ort, an dem sich die meisten Ihrer Konfigurationen befinden.

prod.py importiert alles aus dem Common und überschreibt alles, was zum Überschreiben benötigt wird:

from __future__ import absolute_import # optional, but I like it
from .common import *

# Production overrides
DEBUG = False
#...

In ähnlicher Weise importiert dev.py alles aus common.py und überschreibt, was zum Überschreiben erforderlich ist.

Schließlich entscheiden Sie mit __init__.py, welche Einstellungen geladen werden sollen, und Sie speichern auch Geheimnisse (daher sollte diese Datei nicht versioniert werden):

from __future__ import absolute_import
from .prod import *  # or .dev if you want dev

##### Django SECRETS
SECRET_KEY = '([email protected]&57...'
DATABASES['default']['PASSWORD'] = 'f9kGH...'

##### OTHER SECRETS
AWS_SECRET_ACCESS_KEY = "h50fH..."

Was mir an dieser Lösung gefällt, ist:

  1. Alles ist in Ihrem Versionierungssystem außer Geheimnissen
  2. Die meisten Konfigurationen befinden sich an einem Ort: common.py.
  3. Prod-spezifische Dinge gehen in prod.py, dev-spezifische Dinge in dev.py. Es ist einfach.
  4. Sie können Dinge von common.py in prod.py oder dev.py überschreiben, und Sie können alles in __init__.py überschreiben.
  5. Es ist unkomplizierter Python. Keine Re-Import-Hacks.
63
MiniQuark

Ich verwende eine leicht modifizierte Version des von Harper Shelby geposteten "if DEBUG" -Stils der Einstellungen. Abhängig von der Umgebung (win/linux/etc.) Muss der Code möglicherweise etwas angepasst werden.

Ich habe in der Vergangenheit "if DEBUG" verwendet, aber ich stellte fest, dass ich gelegentlich Tests mit DEUBG auf False durchführen musste. Was ich wirklich unterscheiden wollte, ob die Umgebung Produktion oder Entwicklung war, gab mir die Freiheit, den DEBUG-Level zu wählen.

PRODUCTION_SERVERS = ['WEBSERVER1','WEBSERVER2',]
if os.environ['COMPUTERNAME'] in PRODUCTION_SERVERS:
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION
TEMPLATE_DEBUG = DEBUG

# ...

if PRODUCTION:
    DATABASE_Host = '192.168.1.1'
else:
    DATABASE_Host = 'localhost'

Ich würde diese Art der Einstellung immer noch als in Arbeit befindlich betrachten. Ich habe keine Möglichkeit gesehen, mit Django-Einstellungen umzugehen, die alle Grundlagen abdeckten, und gleichzeitig kein kompliziertes Setup darstellte (mit den 5x-Einstellungsdatei-Methoden bin ich nicht schlecht).

20
T. Stone

Ich benutze ein settings_local.py und ein settings_production.py. Nachdem ich verschiedene Optionen ausprobiert hatte, stellte ich fest, dass es einfach ist, Zeit mit komplexen Lösungen zu verschwenden, wenn sich zwei Einstellungsdateien einfach und schnell anfühlen.

Wenn Sie für Ihr Django-Projekt mod_python/mod_wsgi verwenden, müssen Sie es auf Ihre Einstellungsdatei zeigen. Wenn Sie es auf app/settings_local.py auf Ihrem lokalen Server und app/settings_production.py auf Ihrem Produktionsserver verweisen, wird das Leben leicht. Bearbeiten Sie einfach die entsprechende Einstellungsdatei und starten Sie den Server neu (Django-Entwicklungsserver wird automatisch neu gestartet).

14
Kai

Ich verwalte meine Konfigurationen mit Hilfe von Django-Split-Einstellungen

Es ist ein Drop-In-Ersatz für die Standardeinstellungen. Es ist einfach und dennoch konfigurierbar. Ein Refactoring Ihrer vorhandenen Einstellungen ist nicht erforderlich.

Hier ist ein kleines Beispiel (Datei example/settings/__init__.py):

from split_settings.tools import optional, include
import os

if os.environ['Django_SETTINGS_MODULE'] == 'example.settings':
    include(
        'components/default.py',
        'components/database.py',
        # This file may be missing:
        optional('local_settings.py'),

        scope=globals()
    )

Das ist es.

Aktualisieren

Ich schrieb einen blog post über die Verwaltung der Einstellungen von Django mit Django-split-sttings. Guck mal!

7
sobolevn

Das Problem bei den meisten dieser Lösungen ist, dass Sie entweder Ihre lokalen Einstellungen vor den allgemeinen oder nach anwenden.

So ist es unmöglich, Dinge wie zu überschreiben

  • die env-spezifischen Einstellungen definieren die Adressen für den memcached-Pool. In der Haupteinstellungsdatei wird dieser Wert zum Konfigurieren des Cache-Backends verwendet
  • die Env-spezifischen Einstellungen fügen Apps/Middleware zur Standard-App hinzu oder entfernen sie

zur selben Zeit.

Eine Lösung kann mithilfe von "ini" -Stil-Konfigurationsdateien mit der ConfigParser-Klasse implementiert werden. Es unterstützt mehrere Dateien, Lazy-String-Interpolation, Standardwerte und viele andere Goodies. Wenn mehrere Dateien geladen wurden, können weitere Dateien geladen werden, und ihre Werte überschreiben die vorherigen, falls vorhanden.

Sie laden eine oder mehrere Konfigurationsdateien, abhängig von der Computeradresse, Umgebungsvariablen und sogar Werten in zuvor geladenen Konfigurationsdateien. Dann verwenden Sie einfach die geparsten Werte, um die Einstellungen zu füllen. 

Eine Strategie, die ich erfolgreich angewendet habe, war:

  • Laden Sie eine Standard defaults.ini-Datei
  • Überprüfen Sie den Rechnernamen und laden Sie alle Dateien, die dem umgekehrten FQDN entsprechen, von der kürzesten Übereinstimmung bis zur längsten Übereinstimmung (also habe ich net.ini geladen, dann net.domain.ini, dann net.domain.webserver01.ini, wobei möglicherweise alle Werte der vorherigen überschrieben werden). Dieses Konto auch für Entwickler-Computer, sodass jeder seinen bevorzugten Datenbanktreiber usw. für die lokale Entwicklung einrichten kann
  • Prüfen Sie, ob ein "Clustername" deklariert ist, und laden Sie in diesem Fall cluster.cluster_name.ini, um z. B. Datenbank- und Cache-IPs zu definieren

Als ein Beispiel für etwas, das Sie damit erreichen können, können Sie einen "Subdomain" -Wert pro-env definieren, der dann in den Standardeinstellungen (als hostname: %(subdomain).whatever.net) verwendet wird, um alle erforderlichen Hostnamen und Cookies zu definieren, die Django benötigt.

Dies ist wie DRY ich konnte bekommen, die meisten (vorhandenen) Dateien hatten nur 3 oder 4 Einstellungen. Darüber hinaus musste ich die Kundenkonfiguration verwalten. Daher gab es einen zusätzlichen Satz von Konfigurationsdateien (mit Datenbanknamen, Benutzern und Kennwörtern, zugewiesene Subdomänen usw.), eine oder mehrere pro Kunde.

Man kann dies so niedrig oder so hoch wie nötig skalieren. Sie geben einfach die Konfigurationsschlüssel in die Konfigurationsdatei ein, die Sie pro Umgebung konfigurieren möchten. Sobald eine neue Konfiguration erforderlich ist, geben Sie den vorherigen Wert in die Standardkonfiguration ein und überschreiben Sie ihn wo nötig.

Dieses System hat sich als zuverlässig erwiesen und funktioniert gut mit der Versionskontrolle. Es wurde seit langem für die Verwaltung von zwei separaten Anwendungsclustern (15 oder mehr separate Instanzen der Django-Site pro Computer) mit mehr als 50 Kunden verwendet, bei denen sich die Größe und Mitglieder der Cluster je nach Stimmung des Sysadmin ändern. .

6
rewritten

TL; DR: Der Trick besteht darin, os.environment Zu ändern, bevor Sie settings/base.py In settings/<purpose>.py Importieren. Dies vereinfacht die Dinge erheblich.


Wenn ich nur an all diese ineinander verschlungenen Dateien denke, bekomme ich Kopfschmerzen. Kombinieren, Importieren (manchmal bedingt), Überschreiben, Patchen der bereits festgelegten Einstellungen für den Fall, dass sich die Einstellung von DEBUG später ändert. Was ein Alptraum!

Im Laufe der Jahre habe ich alle möglichen Lösungen durchlaufen. Sie alle funktionieren etwas , sind aber so schmerzhaft zu handhaben. WTF! Brauchen wir wirklich all diesen Ärger? Wir haben mit nur einer settings.py - Datei begonnen. Jetzt brauchen wir eine Dokumentation, um all dies in der richtigen Reihenfolge richtig zusammenzufügen!

Ich hoffe, ich habe endlich den (meinen) Sweet Spot mit der folgenden Lösung erreicht.

Lassen Sie uns die Ziele zusammenfassen (einige gemeinsame, einige meine)

  1. Halten Sie Geheimnisse geheim - bewahren Sie sie nicht in einem Repo auf!

  2. Setzen/Lesen von Schlüsseln und Geheimnissen durch Umgebungseinstellungen, 12-Faktor-Stil .

  3. Haben Sie sinnvolle Fallback-Standardeinstellungen. Idealerweise brauchen Sie für die lokale Entwicklung neben den Standardeinstellungen nichts mehr.

  4. … Aber versuchen Sie, die Standardproduktion sicher zu halten. Es ist besser, ein Überschreiben der Einstellungen lokal zu verpassen, als daran zu denken, die Standardeinstellungen produktionssicher anzupassen.

  5. Haben Sie die Möglichkeit, DEBUG auf eine Weise ein-/auszuschalten, die Auswirkungen auf andere Einstellungen haben kann (z. B. mit komprimiertem Javascript oder nicht).

  6. Das Umschalten zwischen Zweckeinstellungen, wie z. B. Lokal/Testen/Inszenieren/Produktion, sollte nur auf Django_SETTINGS_MODULE Basieren, nicht mehr.

  7. … Aber erlauben Sie eine weitere Parametrierung durch Umgebungseinstellungen wie DATABASE_URL.

  8. … Erlauben Sie ihnen auch, verschiedene Zweckeinstellungen zu verwenden und sie lokal nebeneinander auszuführen, z. Produktionssetup auf lokaler Entwicklermaschine, um auf die Produktionsdatenbank zuzugreifen oder komprimierte Stylesheets zu rauchen.

  9. Scheitern, wenn eine Umgebungsvariable nicht explizit festgelegt ist (mindestens ein leerer Wert erforderlich ist), insbesondere in der Produktion, z. EMAIL_Host_PASSWORD.

  10. Reagieren Sie auf die Standardeinstellung Django_SETTINGS_MODULE In manage.py während Django-admin startproject

  11. Halten Sie die Bedingungen auf ein Minimum, wenn die Bedingung dem beabsichtigten Umgebungstyp entspricht (z. B. für die Produktionssatz-Protokolldatei und deren Rotation), überschreiben Sie die Einstellungen in den zugehörigen beabsichtigten Umgebungen Einstellungsdatei.

Nicht

  1. Lassen Sie die Einstellung Django Django_SETTINGS_MODULE nicht aus einer Datei lesen.
    Pfui! Denken Sie daran, wie meta das ist. Wenn Sie eine Datei (wie docker env) benötigen, lesen Sie diese in die Umgebung, bevor Sie einen Django) - Prozess starten.

  2. Überschreiben Sie Django_SETTINGS_MODULE nicht in Ihrem Projekt-/App-Code, z. basierend auf Hostname oder Prozessname.
    Wenn Sie nicht in der Lage sind, Umgebungsvariablen festzulegen (wie für setup.py test), Führen Sie dies in Tools aus, bevor Sie Ihren Projektcode ausführen.

  3. Vermeiden Sie Magie und das Patchen, wie Django liest seine Einstellungen, die Einstellungen vorverarbeiten, aber nicht danach stören.

  4. Kein komplizierter logischer Unsinn. Die Konfiguration sollte repariert und materialisiert und nicht sofort berechnet werden. Das Bereitstellen von Fallback-Standardeinstellungen ist hier nur logisch genug.
    Wollen Sie wirklich debuggen, warum haben Sie vor Ort die richtigen Einstellungen, aber in der Produktion auf einem Remote-Server, auf einem von hundert Rechnern, etwas anders berechnet? Oh! Unit-Tests? Für Einstellungen? Ernsthaft?

Lösung

Meine Strategie besteht aus exzellentem Django-environ , das mit ini -Stildateien verwendet wird und os.environment - Standardeinstellungen für die lokale Entwicklung bereitstellt, einige minimale und kurze settings/<purpose>.py - Dateien, die habe einen import settings/base.py [~ # ~] nachdem [~ # ~] der os.environment aus einem INI Datei. Dies gibt uns effektiv eine Art Einstellungsinjektion.

Der Trick besteht darin, os.environment Zu ändern, bevor Sie settings/base.py Importieren.

Um das vollständige Beispiel zu sehen, machen Sie das Repo: https://github.com/wooyek/Django-settings-strategy

.
│   manage.py
├───data
└───website
    ├───settings
    │   │   __init__.py   <-- imports local for compatibility
    │   │   base.py       <-- almost all the settings, reads from proces environment 
    │   │   local.py      <-- a few modifications for local development
    │   │   production.py <-- ideally is empty and everything is in base 
    │   │   testing.py    <-- mimics production with a reasonable exeptions
    │   │   .env          <-- for local use, not kept in repo
    │   __init__.py
    │   urls.py
    │   wsgi.py

einstellungen/.env

Standard für lokale Entwicklung. Eine geheime Datei zum Festlegen der meist erforderlichen Umgebungsvariablen. Setzen Sie sie auf leere Werte, wenn sie in der lokalen Entwicklung nicht benötigt werden. Wir geben hier Standardwerte an und nicht in settings/base.py, Damit ein Fehler auf einem anderen Computer auftritt, wenn dieser in der Umgebung fehlt.

settings/local.py

Was hier passiert, ist das Laden der Umgebung aus settings/.env Und das Importieren der allgemeinen Einstellungen aus settings/base.py. Danach können wir einige überschreiben, um die lokale Entwicklung zu erleichtern.

import logging
import environ

logging.debug("Settings loading: %s" % __file__)

# This will read missing environment variables from a file
# We wan to do this before loading a base settings as they may depend on environment
environ.Env.read_env(DEBUG='True')

from .base import *

ALLOWED_HOSTS += [
    '127.0.0.1',
    'localhost',
    '.example.com',
    'vagrant',
    ]

# https://docs.djangoproject.com/en/1.6/topics/email/#console-backend
EMAIL_BACKEND = 'Django.core.mail.backends.console.EmailBackend'
# EMAIL_BACKEND = 'Django.core.mail.backends.dummy.EmailBackend'

LOGGING['handlers']['mail_admins']['email_backend'] = 'Django.core.mail.backends.dummy.EmailBackend'

# Sync task testing
# http://docs.celeryproject.org/en/2.5/configuration.html?highlight=celery_always_eager#celery-always-eager

CELERY_ALWAYS_EAGER = True
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True

einstellungen/produktion.py

Für die Produktion sollten wir keine Umgebungsdatei erwarten, aber es ist einfacher, eine zu haben, wenn wir etwas testen. Aber auf jeden Fall, damit nicht einige Standardeinstellungen inline bereitgestellt werden, kann settings/base.py Entsprechend reagieren.

environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
from .base import *

Das Hauptinteresse liegt hier auf den Überschreibungen von DEBUG und ASSETS_DEBUG. Sie werden NUR dann auf den python os.environ Angewendet, wenn sie von FEHLEN die Umgebung und die Datei.

Dies sind unsere Produktionsstandards. Sie müssen nicht in die Umgebung oder in die Datei gestellt werden, sondern können bei Bedarf überschrieben werden. Ordentlich!

einstellungen/base.py

Dies sind hauptsächlich Ihre Vanilla Django) Einstellungen, mit ein paar Bedingungen und viel Lesen aus der Umgebung. Fast alles ist hier drin, um alle vorgesehenen Umgebungen konsistent und so ähnlich wie möglich zu halten.

Die Hauptunterschiede sind unten (ich hoffe, diese sind selbsterklärend):

import environ

# https://github.com/joke2k/Django-environ
env = environ.Env()

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Where BASE_DIR is a Django source root, ROOT_DIR is a whole project root
# It may differ BASE_DIR for eg. when your Django project code is in `src` folder
# This may help to separate python modules and *Django apps* from other stuff
# like documentation, fixtures, docker settings
ROOT_DIR = BASE_DIR

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG', default=False)

INTERNAL_IPS = [
    '127.0.0.1',
]

ALLOWED_HOSTS = []

if 'ALLOWED_HOSTS' in os.environ:
    hosts = os.environ['ALLOWED_HOSTS'].split(" ")
    BASE_URL = "https://" + hosts[0]
    for Host in hosts:
        Host = Host.strip()
        if Host:
            ALLOWED_HOSTS.append(Host)

SECURE_SSL_REDIRECT = env.bool('SECURE_SSL_REDIRECT', default=False)

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

if "DATABASE_URL" in os.environ:  # pragma: no cover
    # Enable database config through environment
    DATABASES = {
        # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
        'default': env.db(),
    }

    # Make sure we use have all settings we need
    # DATABASES['default']['ENGINE'] = 'Django.contrib.gis.db.backends.postgis'
    DATABASES['default']['TEST'] = {'NAME': os.environ.get("DATABASE_TEST_NAME", None)}
    DATABASES['default']['OPTIONS'] = {
        'options': '-c search_path=gis,public,pg_catalog',
        'sslmode': 'require',
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'Django.db.backends.sqlite3',
            # 'ENGINE': 'Django.contrib.gis.db.backends.spatialite',
            'NAME': os.path.join(ROOT_DIR, 'data', 'db.dev.sqlite3'),
            'TEST': {
                'NAME': os.path.join(ROOT_DIR, 'data', 'db.test.sqlite3'),
            }
        }
    }

STATIC_ROOT = os.path.join(ROOT_DIR, 'static')

# Django-assets
# http://Django-assets.readthedocs.org/en/latest/settings.html

ASSETS_LOAD_PATH = STATIC_ROOT
ASSETS_ROOT = os.path.join(ROOT_DIR, 'assets', "compressed")
ASSETS_DEBUG = env('ASSETS_DEBUG', default=DEBUG)  # Disable when testing compressed file in DEBUG mode
if ASSETS_DEBUG:
    ASSETS_URL = STATIC_URL
    ASSETS_MANIFEST = "json:{}".format(os.path.join(ASSETS_ROOT, "manifest.json"))
else:
    ASSETS_URL = STATIC_URL + "assets/compressed/"
    ASSETS_MANIFEST = "json:{}".format(os.path.join(STATIC_ROOT, 'assets', "compressed", "manifest.json"))
ASSETS_AUTO_BUILD = ASSETS_DEBUG
ASSETS_MODULES = ('website.assets',)

Das letzte Bit zeigt die Kraft hier. ASSETS_DEBUG Hat eine sinnvolle Voreinstellung, die in settings/production.py Überschrieben werden kann und sogar von einer Umgebungseinstellung überschrieben werden kann! Yay!

In der Tat haben wir eine gemischte Hierarchie von Bedeutung:

  1. settings/.py - Setzt die Standardeinstellungen auf Grundlage des Verwendungszwecks und speichert keine Geheimnisse
  2. settings/base.py - wird hauptsächlich von der Umgebung gesteuert
  3. prozessumgebungseinstellungen - 12-Faktor-Baby!
  4. settings/.env - lokale Standardeinstellungen für einen einfachen Start
5

Ich arbeite auch mit Laravel und ich mag die Implementierung dort. Ich habe versucht, es nachzuahmen und mit der von T. Stone vorgeschlagenen Lösung zu kombinieren (siehe oben):

PRODUCTION_SERVERS = ['*.webfaction.com','*.whatever.com',]

def check_env():
    for item in PRODUCTION_SERVERS:
        match = re.match(r"(^." + item + "$)", socket.gethostname())
        if match:
            return True

if check_env():
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION

Vielleicht würde Ihnen so etwas helfen.

4
Robert Kuzma

Denken Sie daran, dass settings.py eine Live-Codedatei ist. Angenommen, Sie haben DEBUG nicht für die Produktion festgelegt (was sich als bewährte Methode erweist), können Sie Folgendes tun:

if DEBUG:
    STATIC_PATH = /path/to/dev/files
else:
    STATIC_PATH = /path/to/production/files

Ziemlich einfach, aber theoretisch könnte man die Komplexität auf der Grundlage des Wertes von DEBUG erhöhen - oder einer anderen Variablen- oder Codeüberprüfung, die Sie verwenden wollten.

4
Harper Shelby

Ich verwende eine Variante des oben genannten jpartogi, das ich etwas kürzer finde:

import platform
from Django.core.management import execute_manager 

computername = platform.node()

try:
  settings = __import__(computername + '_settings')
except ImportError: 
  import sys
  sys.stderr.write("Error: Can't find the file '%r_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run Django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % (computername, __file__))
  sys.exit(1)

if __== "__main__":
  execute_manager(settings)

Grundsätzlich habe ich auf jedem Computer (Entwicklung oder Produktion) die entsprechende hostname_settings.py -Datei, die dynamisch geladen wird.

3
stratosgear

Es gibt auch Django Classy Settings. Ich persönlich bin ein großer Fan davon. Es wurde von einem der aktivsten Leute im Django IRC gebaut. Sie würden Umgebungsvariablen verwenden, um Dinge festzulegen.

http://Django-classy-settings.readthedocs.io/de/latest/

3
SudoKid

Meine Lösung für dieses Problem ist auch eine Mischung aus einigen Lösungen, die hier bereits genannt wurden:

  • Ich behalte eine Datei namens local_settings.py, die den Inhalt USING_LOCAL = True in dev und USING_LOCAL = False in prod hat
  • In settings.py importiere ich diese Datei, um die Einstellung USING_LOCAL zu erhalten

Ich stelle dann alle meine umgebungsabhängigen Einstellungen auf diese ein:

DEBUG = USING_LOCAL
if USING_LOCAL:
    # dev database settings
else:
    # prod database settings

Ich ziehe es vor, zwei separate settings.py-Dateien zu haben, die ich pflegen muss, da ich meine Einstellungen in einer einzigen Datei strukturieren kann, anstatt sie auf mehrere Dateien zu verteilen. Wenn ich eine Einstellung aktualisiere, vergesse ich nicht, dies für beide Umgebungen zu tun.

Natürlich hat jede Methode ihre Nachteile und diese ist keine Ausnahme. Das Problem hierbei ist, dass ich die local_settings.py-Datei nicht überschreiben kann, wenn ich meine Änderungen in die Produktion schiebe, was bedeutet, dass ich nicht alle Dateien blind kopieren kann, aber damit kann ich leben.

3
Miguel Ventura

Für die meisten meiner Projekte verwende ich folgendes Muster:

  1. Erstellen Sie die Datei settings_base.py, in der die Einstellungen gespeichert werden, die für alle Umgebungen gelten 
  2. Wenn ich eine neue Umgebung mit spezifischen Anforderungen verwenden muss, erstelle ich eine neue Einstellungsdatei (z. B. "settings_local.py"), die den Inhalt von "settings_base.py" erbt und die entsprechenden Einstellungsvariablen überschreibt/hinzufügt (from settings_base import *)

(Um manage.py mit einer benutzerdefinierten Einstellungsdatei auszuführen, verwenden Sie einfach die Befehlsoption --settings: manage.py <command> --settings=settings_you_wish_to_use.py)

3
dzida

Um eine andere settings-Konfiguration in einer anderen Umgebung zu verwenden, erstellen Sie eine andere Einstellungsdatei. Starten Sie den Server in Ihrem Implementierungsskript mit dem Parameter --settings=<my-settings.py> , über den Sie verschiedene Einstellungen in verschiedenen Umgebungen verwenden können.

Vorteile dieses Ansatzes:

  1. Ihre Einstellungen sind modular für jede Umgebung

  2. Sie können den master_settings.py, der die Basiskonfiguration enthält, in den environmnet_configuration.py importieren und die Werte überschreiben, die Sie in dieser Umgebung ändern möchten.

  3. Wenn Sie über ein großes Team verfügen, kann jeder Entwickler einen eigenen local_settings.py haben, den er zum Code-Repository hinzufügen kann, ohne die Serverkonfiguration zu ändern. Sie können diese lokalen Einstellungen zu .gitnore hinzufügen, wenn Sie git oder .hginore verwenden, wenn Sie Mercurial für Versionskontrolle (oder eine andere) verwenden. Auf diese Weise sind die lokalen Einstellungen nicht einmal Teil der eigentlichen Codebasis, um den Code sauber zu halten.

2

1 - Erstellen Sie einen neuen Ordner in Ihrer App und benennen Sie die Einstellungen.

2 - Erstellen Sie nun eine neue init . Py-Datei und schreiben Sie darin

    from .base import *

    try:

        from .local import *

    except:

        pass

     try:

         from .production import *

     except:

         pass

3 - Erstellen Sie drei neue Dateien im Einstellungsordner mit den Namen local.py und production.py und base.py

4 - Inside base.py kopiert den gesamten Inhalt des vorherigen settings.p-Ordners und benennt ihn mit einem anderen Namen um, sagen Sie old_settings.py

5 - Ändern Sie in base.py Ihren BASE_DIR-Pfad, um auf Ihren neuen Einstellungspfad zu verweisen

Alter Pfad-> BASE_DIR = os.path.dirname (os.path.dirname (os.path.abspath ( file )))

Neuer Pfad -> BASE_DIR = os.path.dirname (os.path.dirname (os.path.dirname (os.path.abspath ( file )))

auf diese Weise kann das Projektverzeichnis nun strukturiert und zwischen Produktion und lokaler Entwicklung verwaltet werden.

1
Jack Ryan

Als Alternative zum Verwalten einer anderen Datei, wenn Sie Folgendes tun: Wenn Sie git oder ein anderes VCS verwenden, um Codes von lokal auf den Server zu übertragen, können Sie die Einstellungsdatei zu .gitignore hinzufügen.

Dadurch können Sie an beiden Orten problemlos unterschiedliche Inhalte haben. SO auf dem Server können Sie eine unabhängige Version von settings.py konfigurieren und alle Änderungen, die auf dem lokalen Server vorgenommen wurden, wirken sich auf dem Server aus und umgekehrt.

Außerdem entfernt es die Datei settings.py von github, den großen Fehler, den ich bei vielen Neulingen gesehen habe.

1
sprksh

Ich unterscheide es in manage.py und habe zwei separate Einstellungsdateien erstellt: local_settings.py und prod_settings.py. 

In manage.py überprüfe ich, ob der Server lokaler Server oder Produktionsserver ist. Wenn es sich um einen lokalen Server handelt, wird local_settings.py geladen, und es ist ein Produktionsserver, auf dem prod_settings.py geladen wird. Grundsätzlich sieht es so aus:

#!/usr/bin/env python
import sys
import socket
from Django.core.management import execute_manager 

ipaddress = socket.gethostbyname( socket.gethostname() )
if ipaddress == '127.0.0.1':
    try:
        import local_settings # Assumed to be in the same directory.
        settings = local_settings
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'local_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run Django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)
else:
    try:
        import prod_settings # Assumed to be in the same directory.
        settings = prod_settings    
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'prod_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run Django-admin.py, passing it your settings module.\n(If the file prod_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)

if __== "__main__":
    execute_manager(settings)

Ich fand es einfacher, die Einstellungsdatei in zwei separate Dateien aufzuteilen, anstatt viele ifs in der Einstellungsdatei auszuführen.

1
Joshua Partogi

Ich hatte meine Einstellungen wie folgt aufgeteilt 

settings/
     |
     |- base.py
     |- dev.py
     |- prod.py  

Wir haben 3 Umgebungen 

  • dev
  • inszenierung
  • produktion 

Inszenierung und Produktion sollten jetzt offensichtlich die maximal mögliche ähnliche Umgebung haben. Also behielten wir prod.py für beide.

Es gab jedoch einen Fall, in dem ich feststellen musste, dass der laufende Server ein Produktionsserver ist. @T. Die Antwort von Stone half mir, wie folgt zu schreiben. 

from socket import gethostname, gethostbyname  
PROD_HOSTS = ["webserver1", "webserver2"]

DEBUG = False
ALLOWED_HOSTS = [gethostname(), gethostbyname(gethostname()),]


if any(Host in PROD_HOSTS for Host in ALLOWED_HOSTS):
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True  
1
Kishor Pawar

Ich denke, die beste Lösung wird von @T vorgeschlagen. Stone, aber ich weiß nicht, warum man die DEBUG-Flagge in Django nicht benutzt. Ich schreibe den folgenden Code für meine Website:

if DEBUG:
    from .local_settings import *

Die einfachen Lösungen sind immer besser als komplexe.

0
seyedrezafar

Mehrere Versionen von settings.py erstellen ist ein Anti-Pattern für 12 Factor App-Methodik . Use python-decouple oder Django-environ .

0