Django uwsgi import error - django

I have a Django project with one app called subscribe. In root urls.py I use include from subscribe's urls.py.
I put to INSTALLED_APPS subscribe and in subscribe's urls.py I use subscribe.views.<name> for call my views. When server run as python manage.py runserver locally all works fine. But when server run on nginx+uwsgi with virtualenv, I've got ImportError: No module named subscribe.
When I changing subscribe to project.subscribe in INSTALLED_APPS and in subscribe's urls.py changing subscribe.views.<name> to project.subscribe.views.<name> all works fine.
uwsgi config:
[uwsgi]
socket = 127.0.0.1:9003
workers = 2
master = true
virtualenv = /home/user/python
chdir = /home/user
env = DJANGO_SETTINGS_MODULE=project.settings
module = django.core.handlers.wsgi:WSGIHandler()
daemonize = /home/user/uwsgi.log
Why should I use absolute path import and how I can change it to relative back on nginx+uwsgi with virtualenv?

Your uwsgi config should include pythonpath=/path/where/lives/settings.py/ directive, so python interpreter will know where to find your apps.
Find more information about uwsgi config options:
http://projects.unbit.it/uwsgi/wiki/Doc
http://projects.unbit.it/uwsgi/wiki/Example

Related

How to add a sub-app in django to INSTALLED_APPS?

I have the structure of my project:
project
———— project
———— app
———————— subapp
———— manage.py
I added my sub-app to INSTALLED_APPS like that:
INSTALLED_APPS = ['app.apps.AppConfig', 'app.subapp.apps.SubapConfig']
But it doesn't works. Django gives me an error message:
No module named 'news' and Cannot import 'news'. Check that
'apps.subapp.apps.SubapConfig.name' is correct.
Let's assume I've created an app named polls with the following command:
python manage.py startapp polls
Now I want to create a sub-app named subpoll inside the main app means inside the polls folder. So, how do I do that?
At first, I'll create a directory My_App_Name inside the /polls folder. In my case, I'll create a subpoll folder inside the polls folder.
After that, run the following command to create the new app.
python manage.py startapp My_App_Name ./polls/Your_Apps_Folder_Name/
So, in my case the following command will be like:
python manage.py startapp subpoll ./polls/subpoll/
Finally, I'll add just created apps name in the settings.py like below:
INSTALLED_APPS = [
...,
'polls',
'polls.subpoll',
]
I had a similar issue. In the apps.py Config class you need to set name to be the full dotted path. So based on the structure you give:
project
———— project
———— app
———————— subapp
———— manage.py
You would have:
class AppConfig(AppConfig):
name = "app"
and
class SubappConfig(AppConfig):
name = "app.subapp"
This should then work for you.

Declare Django settings to use with mod_wsgi/apache

I have multiple settings files in my Django project (base.py, local.py, production.py).
Locally, I'm kicking off the Django dev server via
python manage.py runserver --settings=config.settings.local
How can I tell mod_wsgi to use the same file? I'm testing this on my local apache instance, but will need to figure out the same thing for my production apache instance.
--settings=config.settings.production
Current httpd-vhosts.conf:
WSGIDaemonProcess secureDash python-path=/Users/user/projects/secureDash_project/secureDash python-home=/Users/user/.venvs/securedash_py3.6
WSGIProcessGroup secureDash
WSGIScriptAlias / /Users/user/projects/secureDash_project/config/wsgi.py
Error that I see in the apache log:
ModuleNotFoundError: No module named 'secureDash.settings'
Django 1.11
mod_wsgi-4.5.15
Apache 2.4.18
You do this by setting the DJANGO_SETTINGS_MODULE environment variable. You can either do this in your Apache vhost configuration, or in the wsgi file itself.
I solved this by adding DJANGO_SETTINGS_MODULE to my secrets.json file in each environment.
secrets.json:
{
"FILENAME": "secrets.json",
"SECRET_KEY": "someSuperSecretiveSecret!",
"DJANGO_SETTINGS_MODULE": "config.settings.local"
}
wsgi.py:
import json
from django.core.exceptions import ImproperlyConfigured
from pathlib import Path
...
# Directory Paths
BASE_DIR = Path(__file__).resolve().parent
# JSON-based secrets module
SECRETS_JSON = str(BASE_DIR) + '/secrets.json'
with open(SECRETS_JSON) as f:
secrets = json.loads(f.read())
def get_secret(setting, secrets=secrets):
'''Get the secret variable or return explicit exception'''
try:
return secrets[setting]
except KeyError:
error_msg = 'Set the {0} environment variable'.format(setting)
raise ImproperlyConfigured(error_msg)
DJANGO_SETTINGS_MODULE = get_secret('DJANGO_SETTINGS_MODULE')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", DJANGO_SETTINGS_MODULE)

Set DJANGO_SETTINGS_MODULE through uwsgi

I am trying to find the best way to split my django settings, and have the different settings files served for dev and prod.
My wsgi file:
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
and in my uwsgi.ini file I have this:
env = DJANGO_SETTINGS_MODULE=project.settings.local
wsgi-file = project/wsgi.py
But the env from the uwsgi.ini file is not passed to wsgi. If I print os.environ in the wsgi file the DJANGO_SETTINGS_MODULE is not set.
Any ideas?
I like doing something like this in wsgi.py:
import os
import socket
socket_name = socket.gethostname()
if "stage" in socket_name:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings.staging')
elif "prod" in socket_name:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings.production')
else:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings.local')
application = get_wsgi_application()
Your method of detecting whether you're on staging, prod, or local can be whatever you'd like, but the os.environ.setdefault command seems like it'll accomplish what you're hoping to do.
My solution was to also set the DJANGO_SETTINGS_MODULE in the bin/activate file. I have added it after export PATH like so:
export PATH
export DJANGO_SETTINGS_MODULE='project.settings.local'
You should find your bin folder in your project environment folder.

uWSGI loads Django apps in wrong order (alphabetically instead of as in the order defined in INSTALLED_APPS)

I have a Django project running in an virtualenv on uwsgi controlled by supervisord.
In the Django project I have a an extra directory 'apps/' where I put all my Django apps. In my settings.py I add the 'apps/' directory to the python path so the Django apps in it are found.
This works very good with runserver. But I have uwsgi in my production environment. When I start the server, the Django apps are load in alphabetical order as they are in the filesystem and not in the order definded by INSTALLED_APPS.
An example: I have these apps in my filesystem:
/home/anton/project/apps/events
/home/anton/project/apps/profiles
/home/anton/project/apps/routes
Profiles are my extended user profiles, routes are bike routes and events depends on routes because an event can have 1..n routes.
So in my INSTALLED_APPS it is defined this way:
INSTALLED_APPS = [
# .. django stuff ..
'profiles',
'routes',
'events',
]
In the models.py of the events app I import models from the routes app. As long as the Django apps are loaded in the order specified in INSTALLED_APPS setting everything works fine. But uWSGI loads the Django apps in alphabetical ordering. And because events is loaded before routes I get the following error in the models.py from events app:
ImportError at /
cannot import name Route
/myproject/app/src/apps/events/models.py in <module>
from routes.models import Route
So when loading the events app, uwsgi does not know about the routes app.
Should'nt it be that uwsgi loads all the python modules (read: Django apps) and then start executing the request?
Every hint is greatly appreciated!
Thanks,
Anton
PS:
Here is my uwsgi.ini configuration (maybe this helps)
[uwsgi]
http-socket = :8081
master = true
workers = 8
pidfile = /tmp/uwsgi-project.pid
chdir = /project/app/src/apps/
pythonpath = /project/app/src/
module = wsgi
virtualenv = /home/anton/.virtualenvs/project/
env = DJANGO_SETTINGS_MODULE=settings
logto = /project/log/uwsgi-bikemap.log
max-requests = 5000
vacuum = true
'/project/app/src/' is where the Django project is. '/project/app/src/apps' is where the Django apps are. The wsgi.py (referenced by module = wsgi) is in '/project/app/src/'

Error: No module named fileupload

I'm attempting to use this ported version of jQuery File Upload (https://github.com/sigurdga/django-jquery-file-upload). I placed the 'fileupload' directory in the root of the project (next my myapp, settings.py) and modified my urls.py file with url(r'^upload/', include('fileupload.urls')), and added 'fileupload', to my INSTALLED_APPS setting in my settings.py file. When I try python manage.py validate (OR shell OR syncdb) I get this error: Error: No module named fileupload
Did I install the application wrong? I have PIL installed and obviously Django (1.4.1).
If you're using Django 1.4, and you've installed the fileupload app in the same directory as the settings.py, then you probably need to use the path myproject.fileupload instead of fileupload.
# settings.py
INSTALLED_APPS = (
...
'myproject.fileupload',
...
)
# urls.py
url(r'^upload/', include('fileupload.urls'))
The alternative would be to move your fileupload app into the parent directory.