Modifying manage.py for development and production - python

My project has a base.py, a dev.py and a production.py (pretty self explanatory).
On my PC I only keep the dev.py and base.py and on the server I only keep production.py and base.py.
While the WSGI isn't an issue, I do find myself always having to go into manage.py after each deployment to change the os.environ.setdefault() setting.
I wanted to change this:
from __future__ import absolute_import, unicode_literals
import os
import sys
if __name__ == "__main__":
try:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings.dev") #or project.settings.production
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
to this:
from __future__ import absolute_import, unicode_literals
import os
import sys
if __name__ == "__main__":
try:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings.dev")
except:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings.production")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
However this still raises an ImportError. Any ideas why? Or do you know a better way of doing this?

A good way to control this is using the DJANGO_SETTINGS_MODULE environment variable in the shells where you want to use manage.py.
The default manage.py should not have to change:
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
As for the ImportError,
I'm not sure we have enough information to debug it.
But basically you need to make sure that the file is either reachable from the current working directory,
or from a directory on PYTHONPATH.
For example, if you run manage.py from the project's root,
and project/settings/dev.py exists, then the value "project.settings.dev" should work.

Related

Why is my_task.delay() working from shell but not apache/wsgi

Celery worker and beat are working fine.
Site loads fine except when I call a url that passes a task to Celery.
manage.py
#!/usr/bin/env python
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ada.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
This is my WSGI file.
import os
import sys
import dotenv
from django.core.wsgi import get_wsgi_application
dotenv.load_dotenv()
def addpath(path):
if path not in sys.path:
sys.path.insert(0, path)
addpath('/opt/ada')
os.environ['DJANGO_SETTINGS_MODULE'] = 'ada.settings'
os.environ['PYTHONPATH'] = '/opt/ada'
os.environ['CELERY_LOADER'] = "django"
application = get_wsgi_application()
celery_config.py
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ada.settings')
app = Celery('ada')
app.config_from_object('django.conf:settings', namespace='')
app.autodiscover_tasks()
init.py
from __future__ import absolute_import, unicode_literals
from ada.celery_config import app as celery_app
__all__ = ('celery_app', )
I don't understand this error.
mod_wsgi (pid=2547): Exception occurred processing WSGI script '/opt/ada/ada/wsgi.py'.
Traceback (most recent call last):
File "/opt/ada/venv/lib/python3.8/site-packages/kombu/utils/objects.py", line 42, in __get__
return obj.__dict__[self.__name__]
KeyError: 'tasks'
Also, I can try and call the same task from the shell and it works.
The problem only manifests when calling a url that and so must be related to my apache2 site conf file, wsgi.py, or something related
What am I missing?
REMOVING the following line from wsgi.py fixes things.
os.environ['CELERY_LOADER'] = "django"
I do not know why it works and would love to understand.

How does Heroku Django picks up settings file during production? Multiple settings

It's my first time deploying so I just want to make sure that I understand.
Basically, how does heroku django determine which setting file to choose when its deployed?
Are there any command that I can type in order to check which setting file its currently using? like if its a prod or dev.
^^ To answer the above question on my own, you set myproject.settings.prod in wsgi file and heroku config:set DJANGO_SETTINGS_MODULE=mysite.settings.prod to tell it to choose your prod settings for production/deploymnent. Am I correct in my understanding? Thanks in advance. Any advice or feedback would be apprecated!
Yes the answer you came up with is logically correct but might not work.
Change your wsgi.py to set DJANGO_SETTINGS_MODULE; looking at where it is being run on: (You will have to set environment variable ENV=Heroku in heroku for this)
import os
from django.core.wsgi import get_wsgi_application
if os.getenv("ENV") == "Heroku":
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.production_settings')
else:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.dev_settings')
application = get_wsgi_application()
You can also change your manage.py to have the same incase you want to use manage.py runserver for development ease:
import os
import sys
def main():
"""Run administrative tasks."""
if os.getenv("ENV") == "Heroku":
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.production_settings')
else:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.dev_settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
Q: Why this approach instead of your solution to directly set the env variable in heroku?
A: I haven't tested it, but on each restart wsgi.py runs os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.settings') overwriting the DJANGO_SETTINGS_MODULE environment variable manually set by you in heroku. So, you will have to set it in wsgi.py.
First of all, I would like to thank you for your answer but I've managed it in a little bit different way. Because I've split settings files and the purpose was to load an appropriate config file based on environment variable I've resolve it by:
if os.environ.get("DJANGO_ENV") == 'prod':
os.environ['DJANGO_SETTINGS_MODULE'] = 'config.settings.prod'
elif os.environ.get("DJANGO_ENV") == 'dev':
os.environ['DJANGO_SETTINGS_MODULE'] = 'config.settings.dev'
elif os.environ.get("DJANGO_ENV") == 'test':
os.environ['DJANGO_SETTINGS_MODULE'] = 'config.settings.test'
Why? Because os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.production_settings') always returned my_app.settings.
So the question is how it works? Pretty simple, firstly "setdefault" checks environment variables for DJANGO_SETTINGS_MODULE, if it didn't found then it is set as is in code (my_app.production.settings) but probably in most cases it will exist there so instead of using setdeault we should assign a new value for this variable like os.environ['DJANGO_SETTINGS_MODULE'] = 'config.settings.prod'

Import Django settings from external script

I have a python script within my Django project designed to run seperate from the Django app. I want to use the settings.py on my Django App how can I do that.
When I try to import
from django.conf import settings
i get
ImportError: No module named DjangoTastypie.settings
My project Structure
I am running using eclipse-> Run as python
Based on #Sardorbek Imomaliev, you should also make your DjangoTastypie in your PYTHONPATH, you can do this in your script.
import os
import sys
import django
from django.conf import settings
sys.path.append("path/to/DjangoTastypie") # path to the parent dir of DjangoTastypie
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
django.setup()
Read https://docs.djangoproject.com/en/1.9/topics/settings/#calling-django-setup-is-required-for-standalone-django-usage
So you basically will need to put this at the beginning of your script
import os
import django
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
django.setup()

How to force import a lib from python site-package?

I am using custom django struct as below:
all settings file in conf, all app in src
and need use below manage.py:
if __name__ == "__main__":
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
SRC_PATH = os.path.join(ROOT_PATH, 'src')
CONF_PATH = os.path.join(ROOT_PATH, 'conf')
sys.path.insert(0, SRC_PATH)
sys.path.insert(0, CONF_PATH)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
And I also need to use celery in django.
But django-celery need a celery.py file in same directory with settings.py.
When runserver ,it would raise ImportError: cannot import name Celery because below code:
sys.path.insert(0, SRC_PATH)
sys.path.insert(0, CONF_PATH)
It import itself! not from site-package, because CONF_PATH is before site-package.
But I can't change that to
sys.path.append(SRC_PATH)
sys.path.append(CONF_PATH)
This way would cause django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
For now, the only way I know is changing celery.py to celery_somename.py, and I have to type this name every time when I start a celery job.
How do I force import a lib from python site-package? Or is there another way to start celery?
You can add at the top of the celery.py module and other modules importing celery:
from __future__ import absolute_import
This will make imports absolute by default, now:
import celery
Will import the installed celery package and not this module.

ImportError : in django in sphinx-python

I am importing my settings.py in conf.py of sphinx.
import settings
from django.core.management import setup_environ
setup_environ(settings)
but i got this error :
Exception occurred:
File "/home/imps/workspace/myproj/myproj/document/source/conf.py", line 20, in <module>
import settings
ImportError: No module named settings
i try also to add the directory of my project:
from myproj import settings
from django.core.management import setup_environ
setup_environ(settings)
but i got this:
Exception occurred:
File "/home/imps/workspace/myproj/myproj/document/source/conf.py", line 20, in <module>
from myproj import settings
ImportError: No module named myproj
do anyone have an idea about my case?
does the sphinx is sensitive about the directory of the project to be documented?
my directory path of my project is :
/home/imps/workspace/myproj/myproj
and i put the sphinx in:
/home/imps/workspace/myproj/myproj/document
I got it fixed by adding this to conf.py:
sys.path.append('/home/imps/workspace/myproj/myproj')
import settings
from django.core.management import setup_environ
setup_environ(settings)
Now I can run make html succesfully.
Is there an __init__.py in /home/imps/workspace/myproj/myproj?
How do you start your program?
python manage.py runserver?
Visit the 127.0.0.1:8000,You can see the website.
If you want to run the the following script: python conf.py, you need set your project path in your python path.You can simply add a line to the head of conf.py:
os.sys.path.append('/home/imps/workspace/myproj/myproj')

Categories