I have this folder structure for django
settings/dev.py
settings/prod.py
settings/test.py
Then i have common settings in settings/common.py in which i check the ENV variable like
if PROD:
from settings.prod import *
Based on ENV variable each one of them will be active
I want to use something like this in my code
from myapp import settings
rather than
from myapp.settings import dev
This is the method which I follow. Learnt this from the book Two Scoops of Django.
Have a file, such as, settings/common.py which will contain the properties/settings which are common in dev, prod and test environment. (You already have this.)
The other 3 files should:
Import the common settings from the settings/common.py by adding the line from .common import *
And should contain settings for its own corresponding environment.
The manage.py file decides which settings file to import depending on the OS environment variable, DJANGO_SETTINGS_MODULE. So, for test environment the value of DJANGO_SETTINGS_MODULE should be mysite.settings.test
Links for reference:
Django documentation for django-admin utility - Link
Two Scoops of Django sample project - Link
Preserve your settings folder structure and create __init__.py there.
Please, use code below in your settings/__init__.py:
import os
# DJANGO_SERVER_TYPE
# if 1: Production Server
# else if 2: Test Server
# else: Development Server
server_type = os.getenv('DJANGO_SERVER_TYPE')
if server_type==1:
from prod import *
elif server_type==2:
from test import *
else:
from dev import *
Now you can set environment variable called DJANGO_SERVER_TYPE to choose between Production, Test or Development Server and import settings using:
import settings
Related
I'm going through the Django tutorial and wanted to try out database manipulating with a python script but encounter a problem
My script:
from polls.models import Question, Choice
from django.utils import timezone
import numpy as np
#Questions
nquestions=3
q=np.empty([nquestions, 10], dtype=object)
qtext=q
qtext[0]="What's up?"
qtext[1]="What's new?"
qtext[2]="What's old?"
#Choices
q[0,1]="Not much"
q[0,2]="The sky"
q[1,1]="This question"
q[1,2]="This answer"
q[2,1]="No more originality"
q[2,2]="xxxxxxx"
#Check if exists and apply
for i in range(0, len(q)):
q[i,0]=Question(question_text=qtext[i], pub_date=timezone.now())
if Question.objects.filter(question_text=qtext[i]).exists():
pass
else:
q[i,0].question_text=qtext[i]
q[i,0].save()
alen=len(q[i][q[i] != np.array(None)])
for ii in range(0, alen-1):
q[i,0].choice_set.create(choice_text=q[i,ii+1], votes=0)
I get the error django.core.exceptions.appregistrynotready apps aren't loaded yet. I'm running the script from terminal and it's places in the folder that contains the polls-folder (One level over modules.py, which I'm trying to import).
Writing the contents of my script works if i first run in terminal : python manage.py shell. Is there a way for me to run a script to manipulate the database through Djangos API, or do I have to enter information manually or send requests thŕough post?
You need to set the DJANGO_SETTINGS_MODULE environment variable and call django.setup() before you can import your models.
import os
import django
# Change mysite if your project has a different name
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
django.setup()
from polls.models import Question, Choice
...
See the docs for more info.
Another option is to write a custom management command. When you use manage.py to run your management command you don't have to set DJANGO_SETTINGS_MODULE or call django.setup().
I have the following structure of my project
project
--project
----settings
------base.py
------development.py
------testing.py
------secrets.json
--functional_tests
--manage.py
development.py and testing.py 'inherit' from base.py
from .base import *
So, where I have problems
I have the SECRET_KEY for Django in secrets.json, which is stored in settings folder
I load this key like this (saw this in "Two scoops of Django")
import json
from django.core.exceptions import ImproperlyConfigured
key = "secrets.json"
with open(key) as f:
secrets = json.loads(f.read())
def get_secret(setting, secret=secrets):
try:
return secrets[setting]
except KeyError:
error_msg = "Set the {} environment variable".format(setting)
raise ImproperlyConfigured(error_msg)
SECRET_KEY = get_secret("SECRET_KEY")
But when I run python manage.py runserver
Blah-blah-blah
django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
After some investigations I got the following
If I put print(os.getcwd()) inside base.py I get /media/grimel/Home/project/ instead of /media/grimel/Home/project/project/settings/
This code works only if I replace:
key = "secrets.json"
by
key = "project/settings/secrets.json"
Personally, I don't like this solution.
So, questions:
Why, for base.py current working directory is so confusing?
What's a better approach in solving this problem?
The working directory is based on how you run the program, in your case python manage.py runserver hints that your working directory is the one containing manage.py. Beware that this can vary when run as WSGI script or otherwise, so your concern with using key = "project/settings/secrets.json" is valid.
One solution is to use the value of __file__ in base.py, likely to be "project/settings/base.py". I would use something like
import os
BASE_DIR = os.path.dirname(__file__)
key = os.path.join(BASE_DIR, "secrets.json")
To make life simpler why not move secrets.json to your project root and reference
import os
key = os.path.join(BASE_DIR, "secrets.json")
directly. This is platform independent saving you the need to override BASE_DIR at all in your settings file. Don't forget to add your settings file to version control.
I'm using Falcon framework. I want that all standalone classes store in their own dirs( class that serve for /module1/ was inside dir /module1/):
/app
./app.py
/modules
/__init__.py
/module1
...
/module2
...
....
In app.py I have initialization of application:
import falcon
# falcon.API instances are callable WSGI apps
app=falcon.API()
My problems:
how I must organize import of modules, that I can access from
module2 to module1?
How I can access to app variable of app.py from /module2:
I need do this code:
module2_mngr = Module2(CONFIG_FILE)
app.add_route('/module2', module2_mngr)
PS:
Sorry for my English
Simple example where I can use different configuration based on api.debug.DEBUG flag:
create some base path: /somepath/my_app/
create the folder sturcture:
/somepath/my_app/api
/somepath/my_app/api/debug
/somepath/my_app/conf
/somepath/my_app/conf/prod
/somepath/my_app/conf/dev
create empty files:
/somepath/my_app/__init__.py
/somepath/my_app/api/__init__.py
/somepath/my_app/conf/prod/__init__.py
/somepath/my_app/conf/dev/__init__.py
Example main.py (/somepath/my_app/main.py):
import api.debug
api.debug.DEBUG = False
import conf
Setup api.debug.DEBUG == False
/somepath/my_app/api/debug/__init__.py:
DEBUG = False
Create simple "router":
If api.debug.DEBUG is True - loads production configuration.
If api.debug.DEBUG is False - loads development configuration.
So we create
/somepath/my_app/conf/__init__.py:
import api.debug
if not api.debug.DEBUG:
from conf.prod import *
else:
from conf.dev import *
I'm trying to develop my Scrapy application using multiple configurations depending on my environment (e.g. development, production). My problem is that there are some settings that I'm not sure how to set them. For example, if I have to setup my database, in development should be "localhost" and in production has to be another one.
How can I specify these settings when I'm doing scrapy deploy ? Can I set them with a variable in command-line?
You should set the deploy options in your scrapy.cfg file. For example:
[deploy:dev]
url = http://dev_url/
[deploy:production]
url = http://production_url/
With that, you could do:
scrapyd-deploy def
or
scrapyd-deploy production
You can refer to the answer in the following link :
https://alanbuxton.wordpress.com/2018/10/09/using-local-settings-in-a-scrapy-project/
I copy here for quick reference:
Edit the settings.py file so it would read from additional settings files depending on a SCRAPY_ENV environment variable
Move all the settings files to a separate config directory (and change scrapy.cfg so it knew where to look
The magic happens at the end of settings.py:
from importlib import import_module
from scrapy.utils.log import configure_logging
import logging
import os
SCRAPY_ENV=os.environ.get('SCRAPY_ENV',None)
if SCRAPY_ENV == None:
raise ValueError("Must set SCRAPY_ENV environment var")
logger = logging.getLogger(__name__)
configure_logging({'LOG_FORMAT': '%(levelname)s: %(message)s'})
# Load if file exists; incorporate any names started with an
# uppercase letter into globals()
def load_extra_settings(fname):
if not os.path.isfile("config/%s.py" % fname):
logger.warning("Couldn't find %s, skipping" % fname)
return
mdl=import_module("config.%s" % fname)
names = [x for x in mdl.__dict__ if x[0].isupper()]
globals().update({k: getattr(mdl,k) for k in names})
load_extra_settings("secrets")
load_extra_settings("secrets_%s" % SCRAPY_ENV)
load_extra_settings("settings_%s" % SCRAPY_ENV)
Then in the python file you want to get the variables defined in the setting, use the following code
from scrapy.utils.project import get_project_settings
settings = get_project_settings()
env_variable = settings.get('ENV_VARIABLE')
I'd like to have something in my settings like
if ip in DEV_IPS:
SOMESETTING = 'foo'
else:
SOMESETTING = 'bar'
Is there an easy way to get the ip or hostname - also - is this is a bad idea ?
import socket
socket.gethostbyname(socket.gethostname())
However, I'd recommend against this and instead maintain multiple settings file for each environment you're working with.
settings/__init__.py
settings/qa.py
settings/production.py
__init__.py has all of your defaults. At the top of qa.py, and any other settings file, the first line has:
from settings import *
followed by any overrides needed for that particular environment.
One method some shops use is to have an environment variable set on each machine. Maybe called "environment". In POSIX systems you can do something like ENVIRONMENT=production in the user's .profile file (this will be slightly different for each shell and OS). Then in settings.py you can do something like this:
import os
if os.environ['ENVIRONMENT'] == 'production':
# Production
DATABASE_ENGINE = 'mysql'
DATABASE_NAME = ....
else:
# Development