Nginx + uwsgi + Django: Error in url rewriting - django

I'm trying to deploy a Django project on under a sub path of my institute website.
Let's say server IP is: X1.X2.X3.X4.
And xyz.edu/tnp probably points to X1.X2.X3.X4/portal/.
Structure of Django project is like this:
.
|-- project
| |-- app1
| |-- app2
| |-- project_nginx.conf
| |-- project_uwsgi.ini
| |-- db.sqlite3
| |-- manage.py
| |-- media
| |-- README.md
| |-- static
| `-- uwsgi_params
|-- README.md
|-- requirements
| |-- base.txt
| |-- dev.txt
| |-- prod.txt
| `-- test.txt
|-- requirements.txt
|-- static_cdn
| |-- admin
| .....
And my URL scheme in project/urls.py looks like this:
url(r'^app1/', include('app1.urls')),
url(r'^app2/', include('app2.urls')),
url(r'^admin/', include(admin.site.urls)),
On my local server, following scheme is working perfectly.
* 127.0.0.1:8000/app1/
* 127.0.0.1:8000/app1/login/
* 127.0.0.1:8000/app1/homepage/
* 127.0.0.1:8000/app2/somepage
* 127.0.0.1:8000/admin/
I want to map my URLs on my deployment server, so that
xyz.edu/tnp/app1 links to X1.X2.X3.X4/portal/app1 and
xyz.edu/tnp/app2 links to X1.X2.X3.X4/portal/app2
xyz.edu/tnp/admin links to X1.X2.X3.X4/portal/admin
and so on.
The problem is the suffix portal in X1.X2.X3.X4/portal/. When I type xyz.edu/tnp/app1 in browser, the error I'm receiving is
Using the URLconf defined in portal.urls, Django tried these URL patterns, in this order:
^app1/
^app2/
^media/(?P.)$
^static/(?P.)$
The current URL, portal/app1/, didn't match any of these.
Now I think of two approaches:
Manually prepend portal to all urls in project/urls.py
Drop the prefix portal in the portal_nginx.conf file.
First approach isn't working for internal urls. The index page for all apps, i.e. app1, app2 and so on, is working fine but for other urls, they are being rendered as xyz.edu/portal/login instead of xyz.edu/tnp/app1/login.
Second approach, as mentioned here and here, seems promising, but its not working for me. Maybe I'm doing something wrong. Following are my project_nginx.conf and project_uwsgi.ini files.
project_uwsgi.ini
[uwsgi]
chdir = ...
# Django's wsgi file
module = project.wsgi
# the virtualenv (full path)
home = ...
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe
socket = ...
# clear environment on exit
vacuum = true
project_nginx.conf
upstream django {
server unix://.../.../project.sock; # for a file socket
# server 127.0.0.1:8001;
}
# configuration of the server
server {
listen 80;
server_name xyz.edu; # substitute your machine's IP address or FQDN
client_max_body_size 75M; # adjust to taste
# Django media
location /media {
alias /usr/share/nginx/.../project/media;
}
location /static {
alias /usr/share/nginx/.../project/static;
}
# Finally, send all non-media requests to the Django server.
location /portal/ {
rewrite /portal/(.*) /$1 break;
uwsgi_pass django;
# # the uwsgi_params file you installed
include /usr/.../wsgi_param
# uwsgi_param SCRIPT_NAME /portal/;
# uwsgi_modifier1 30;
}
}

Related

Can I put custom settings in Django's settings.py

I have several custom settings I'd like to define in my Django app. Up to this point, I've put them in a constants.py file in each individual app.
myapp/constants.py
HOURS_PER_EVENT = 4
MAX_MEMBERS_PER_EVENTS = 150
MAX_EVENTS_PER_YEAR = 10
...
It just occurred to me I may be able to put these in settings.py and after a quick test everything seems to work fine. Is this allowed or is settings.py reserved for core django settings defined here? If it's not allowed, is there a better place to put these.
Yes it is allowed to extend your application settings, and it is really simple to do it. All that you need to do is a simple manipulation from your current project settings.py to a module settings.
Your file structure is probably like the following:
mysite/
|-- mysite/
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| +-- wsgi.py
+-- manage.py
What you need to do is to change it to something like this:
mysite/
|-- mysite/
| |-- __init__.py
| |-- settings/
| | |-- __init__.py
| | |-- base.py <-- (this is your old settings.py)
| | +-- constants.py
| |-- urls.py
| +-- wsgi.py
+-- manage.py
This is a pattern described in this tutorial.

Django - static/CACHE files not found

I'm using Django 1.10 + uWsgi + nginx.
In Prod mode the static files do not show up, this is what my nginx error-log tells me:
404 ... static/CACHE/js/e3a6fa7588d1.js" failed (2: No such file or directory),
The folder static/CACHE remains empty (so the 404's make sense), but why?
I already set the permissions to 775 for static/CACHE .
nginx conf:
# /etc/nginx/sites/available/mysite_nginx.conf
# the upstream component nginx needs to connect to
upstream bdjango {
server unix:///tmp/mysite.sock; # for a file socket
}
# configuration of the server
server {
# the port your site will be served on
listen 80;
# the domain name it will serve for
server_name dev.mysite.com; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 8M; # adjust to taste
# Django media
location /media {
alias /var/www/mysite/src/media; # your Django project's media files - amend as required
}
location /static {
alias /var/www/mysite/src/static; # your Django project's static files - amend as required
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass adjango;
include /var/www/mysite/src/uwsgi_params; # the uwsgi_params file you installed
}
}
Django settings contains
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__) + "../../../")
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
So, why are my js/css files not in static/CACHE ?
EDIT:
solved it: uwsgi_pass was pointing at the wrong upstream location (which happened to be a different website):
uwsgi_pass adjango;
Are you using CACHE?
Have you defiened STATIC_URL and STATIC_ROOT correctly.
Is DEBUG = False?
Are you using any 3rd party tool to cache/pipline your static files?
It could be that django-compressor is failing.
Have you tried having DEBUG = True and COMPRESS_ENABLED = True in your settings and seeing if it works?
https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_ENABLED
Alternatively, I suggest having ADMINS setup in production so it emails you any errors, or setup sentry in your production setup.

How solve"no python application found check your startup logs" error for Django + uWSGI + nginx stack

I user Django 1.10 with uWSGI and nginx on ubuntu 16.04 and deploy my app with ansible. My project have not default structure, but quite common ( thank Two scoopce for this :).
I use split dev and production settings and config folder instead 'name' project folder. It's looks like this:
|-- config
| |-- __init__.py
| |-- settings
| | |-- __init__.py
| | |-- base.py
| | `-- dev.py
| |-- urls.py
| |-- wsgi_dev.py
| `-- wsgi_production.py
|-- manage.py
`-- requirements.txt
My production.py genarate from ansible with security encrypt and locate in config/settings.
With this config i get "no python application found check your startup logs". Uwsgi don't see my application.
( {{ }} it's jinja2 syntax for ansible )
/etc/uwsgi/sites/{{ project_name }}
[uwsgi]
chdir = {{ django_root }}
home = /home/{{ project_user }}/venvs/{{ project_name }}
module = config.wsgi_production:application
master = true
processes = 5
socket = /run/uwsgi/{{ project_name }}.sock
chown-socket = {{ project_user }}:www-data
chmod-socket = 660
vacuum = true
After several weeks i can find problem in my wsgi.py. It common solution use os.environ['ENV'] for DJANGO_SETTINGS_MODULE, but with deffrent users and permissions its dosen't work.
If you use in your wsgi.py file something like this:
os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings." + os.environ["ENV"]
And have problem with no python application found - split your wsgi file. I can catch that os.environ["ENV"] return empty string. I add it for my all user, use source and etc. But uwsgi in emperior mode don't see it.
You sould use wsgi_dev.py and wsgi_production.py where you can write somethink like this os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings.production". It's not so elegant but solve this problems fine.
For use splitting wsgi you can write something like this in wsgi.py
import os
from django.core.wsgi import get_wsgi_application
if os.environ.get('DEV') is True:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.dev")
else:
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
"config.settings.production")
application = get_wsgi_application()

Where to store static/template files in Django according to "Two Scoops of Django"

I'm a reader and a big fan of the popular book Two Scoops of Django.
The book is full of great ideas, but there is one which is not that clear to me.
The authors advice to create a static and a templates folder in the Django project root.
That template folder is meant for "site-wide templates" (stated at pag.24).
Plus at pag.162 they say that "templates should usually go into the root folder of the Django project... The only exception is when you bundle up an app into a third-party package".
They don't mention it explicitly in ch.12 but I guess it is good to create a folder for each app (with the same name as the app) in the templates root.
Let's suppose that in my icecreamratings Django project I have 2 apps:
flavors with 2 templates: new_flavor.html and details.html
profiles with 1 template: details.html
All templates inherit from base.html.
I guess they would suggest the following structure:
icecreamratings_project/
|-- ...
|-- icecreamratings/ # Django project root
|-- ...
|-- static/
|-- templates/
|-- 404.html
|-- 500.html
|-- base.html
|-- flavors/ # same name as app flavor
| |-- new_flavor.html
| |-- details.html
|-- profiles/ # same name as app profiles
|-- details.html
Did I get it correctly?
On the other hand, the Django official docs suggests to create a static folder in each app and, inside it, a subfolder with the same name as the app, like: my_app/static/my_app/myimage.jpg.
So we have 2 different strategies: a unique template folder and many static folders (one in each app).
Having two different strategies is clearly a bad choice.
So, what do you think of storing in each app a template and static folder?
Something like this:
icecreamratings_project/
|-- ...
|-- icecreamratings/ # Django project root
|-- ...
|-- static/ # site-wide static files
| |-- bootstrap/ # bootstrap source files
| |-- jquery/ # jquery source files
| |-- css/ # css files used by base.html (and others in templates root)
| |-- js/ # javascript files used base.html (and others in templates root)
| |-- img/ # img files files used base.html (and others in templates root)
|-- templates/ # site-wide templates
| |-- 404.html
| |-- 500.html
| |-- base.html
|-- flavors/ # an app
|-- static/
| |-- flavors/ # static files specific for this app
| |-- css/ # css files for flavor app templates
| |-- js/ # javascript files for flavor app templates
| |-- img/ # img files for flavor app templates
|-- templates/ # template files specific for this app
|-- new_flavor.html
|-- details.html
The django official doc does not suggest your to create a static folder in each app. Instead it prefer to store the static dir under the project dir.
Static file namespacing
Now we might be able to get away with putting our static files
directly in my_app/static/ (rather than creating another my_app
subdirectory), but it would actually be a bad idea. Django will use
the first static file it finds whose name matches, and if you had a
static file with the same name in a different application, Django
would be unable to distinguish between them. We need to be able to
point Django at the right one, and the easiest way to ensure this is
by namespacing them. That is, by putting those static files inside
another directory named for the application itself.
The official doc also answered your question about templates structure.
class app_directories.Loader
Loads templates from Django apps on the filesystem. For each app in
INSTALLED_APPS, the loader looks for a templates subdirectory. If
the directory exists, Django looks for templates in there.
This means you can store templates with your individual apps. This
also makes it easy to distribute Django apps with default templates.
The Two Scoops of Django is a great book. But you should read the official doc first.
About templates, as per Django official docs (https://docs.djangoproject.com/en/3.2/ref/templates/api/#loader-types):
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], #add this line
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

why Django put application at the same level of my project folder?

since Django 1.4 (I think) django create a folder for my project when I start a project. Django add a folder for any application I created (with python manage.py startapp) at the same level of my project folder.
Project_name
|---project_name_dir/
|---application_dir/
`---manage.py
I really like the following folder structure:
Project_name
|---project_name_dir/
| |---application_dir/
| | |-- __init__.py
| | |-- models.py
| | |-- tests.py
| | `-- views.py
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
| |---templates/
| | `---application_dir/
| `---static/
| |---css/
| |---font/
| |---img/
| `---js/
|---deployment/
|---documentation/
|---config/
`---manage.py
Because I have a folder with all my django files (project_name_dir/) and other directories for non django files.
So why Django put application at the same level of my project folder?
In Django, the position of the application directory is not considered. Django only uses the name of the application.
Thus, the position of the application is basically a matter of convenience of the programmer.
This is also the reason why two apps should not have the same name: even if they are imported in INSTALLED_APPS as
('app.app1', 'app1')
Django only concerns with the last part after the dot, i.e. app1.
So, in the end, you can use the directory structure you want, as long as the apps' names don't collide and you point to the app on INSTALLED_APPS. Because of this, if there isn't any special reason, you should put them on the project's root, like Django does.