flask static files in redhat openshift cloud - python

I'm trying to deploy flask app to openshift express. The problem is that links to css files are not working. My application folder layout is as follows:
/wsgi
/static
/myapp
/main
/pages
/static
Here "wsgi" and first "static" folders are provided by openshift. However, I put all static files inside main/static, and created flask app inside myapp/_init_.py file as follows:
app = Flask("myapp", template_folder='main/pages', static_folder='main/static')
Now, readme file inside static folder, provided by openshift says that in order to serve static files from different path, I have to use .htaccess file to rewrite url. But I couldn't get it right. Of course, the problem goes away if I copy all my static files to the first "static" folder provided by openshift. I just do not want that. So, can someone help me to serve my static files from my own static folder?

Can you post your .htaccess file? Also, try running a rhc app tail -a appname to see if there is anything in your log files. They might be able to tell you what directories your app is trying to serve content from.

Related

How to deploy Django/React/Webpack app on Digital Ocean through Passenger/Nginx

I'm trying to deploy a web app built with Django/Redux/React/Webpack on a Digital Ocean droplet. I'm using Phusion Passenger and Nginx on the deployment server.
I used create-react-app to build a Django app which has a frontend that uses React/Redux, and a backend api that uses django-rest-framework. I built the frontend using npm run build.
The Django app is configured to look in the frontend/build folder for its files and everything works as expected, including authentication. It's based on this tutorial: http://v1k45.com/blog/modern-django-part-1-setting-up-django-and-react/
In settings.py:
ALLOWED_HOSTS = ['*']
TEMPLATES = [
...
'DIRS': [
os.path.join(BASE_DIR, 'frontend/build'),
],
...
]
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'frontend/build/static'),
]
On my development machine, I activate a Python 3.6 virtual environment and run ./manage.py runserver, and the app is displayed at localhost:3000.
On the deployment server, I've cloned the files into a folder in var/www/ and built the frontend.
I've set up Passenger according to the docs with a file passenger_wsgi.py:
import myapp.wsgi
application = myapp.wsgi.application
And the wsgi.py file is in the djangoapp folder below:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')
application = get_wsgi_application()
The Passenger docs only cover a single-part app:
https://www.phusionpassenger.com/library/walkthroughs/start/python.html
https://www.phusionpassenger.com/library/walkthroughs/deploy/python/digital_ocean/nginx/oss/xenial/deploy_app.html
https://www.phusionpassenger.com/library/deploy/wsgi_spec.html
I've tried cloning the tutorial part 1 code directly onto my server and following the instructions to run it. I got this to work on the server by adding "proxy": "http://localhost:8000" to frontend/package.json. If I run the Django server with ./manage.py runserver --settings=ponynote.production_settings xxx.x.x.x:8000
then the app is correctly served up at myserver:8000. However Passenger is still not serving up the right files.
I have changed wsgi.py to say this:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.production_settings")
application = get_wsgi_application()
The page served by Passenger at URL root now appears to have the right links to the js files such as "text/javascript" src="/static/bundles/js/main.a416835a.js, but the links don't work: the expected js is not present. Passenger is failing to serve the js files from static/bundles/js, even though the Django server can find them.
Very grateful for any help or ideas.
Create-react-app has a fairly opinionated setup for local and production environments.
Locally, running npm start will run a webpack-dev-server, which you would typically access on port 3000. It runs a local nodejs web server to serve the files. You can route requests to your local Django server via the proxy setting.
It's worth noting that at this point there is little or no connection between your React app and Django. If you use the proxy setting, the only thing connecting the two apps is the routing of any requests not handled by your React app to your Django app via the port.
By default in create-react-app (and as noted in the tutorial you mentioned you are following) in production you would run npm run build which will process your create-react-app files into static JS and CSS files, which are then accessed in Django like static files any other Django app.
One thing Django is missing in order to access the static files is a way to know what files are generated when running npm run build. Running a build will typically result in files output like this:
- css
|- main.e0c3cfcb.css
|- main.e0c3cfcb.css.map
- js
|- 0.eb5a2873.chunk.js
|- 0.eb5a2873.chunk.js.map
|- 1.951bae33.chunk.js
|- 1.951bae33.chunk.js.map
A random hash is added to filenames to ensure cache busting. This is where webpack-bundle-tracker and django-webpack-loader come in. When build files are generated, an accompanying file is also created called manifest.json, listing the files created for the build. This is generated in Webpack and picked up by django-webpack-loader so that Django can know which files to import.
It is possible to run a nodejs server in production, or to use server-side rendering, but if you're following the tutorial you mentioned and using create-react-app default settings, then running npm run build and deploying the static files is the simplest, safest option.
Nothing in any of the Passenger deployment links you mention cover anything beyond deploying a Python/Django app - you would need to manage two apps and deployments to have both Django and React running as servers in production.
Note that the tutorial you mention covers how to get your build files into Django in production, but you will need to ensure that you have webpack-bundle-tracker, django-webpack-loader and your Django staticfiles configuration all configured to work together.
The key missing setting was the 'location' setting in the Passenger config file.
Although the Django server serves up the static files, including the build files for your React app, Nginx doesn't see any static files except those in a 'public' directory.
So to deploy a Django app built with Webpack to production, you need to tell Nginx about those files. If you're using Passenger, these settings are probably in a separate Passenger config file. 'alias' is the command to use in this case where the folder has a different name from 'static' (which is where the web page links point).
If you use a virtual environment for your app, you need to specify where Passenger can find the right Python executable.
/etc/nginx/sites-enabled/myapp.conf
server {
listen 80;
server_name xx.xx.xx.xx;
# Tell Passenger where the Python executable is
passenger_python /var/www/myapp/venv36/bin/python3.6;
# Tell Nginx and Passenger where your app's 'public' directory is
# And where to find wsgi.py file
root /var/www/myapp/myapp/myapp;
# Tell Nginx where Webpack puts the bundle folder
location /static/ {
autoindex on;
alias /var/www/myapp/myapp/assets/;
}
# Turn on Passenger
passenger_enabled on;
}
Passenger uses the wsgi.py file as an entry point to your app. You need a passenger_wsgi.py file one level above the wsgi.py file. This tells Passenger where to find the wsgi.py file.
/var/www/myapp/myapp/passenger_wsgi.py
import myapp.wsgi
application = myapp.wsgi.application
/var/www/myapp/myapp/myapp/wsgi.py
If you are using a separate production_settings.py file, make sure this is specified here.
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.production_settings")
application = get_wsgi_application()

Django Deployment Server serving Static Files with only uWSGI

im trying to get my Django App to run using only uWSGI. The project is not that big, so i would really prefer to leave nginx out.
I just can't get uWSGI to show my static files though. I've gone through the settings multiple times and can't find the problem.
I have the STATIC_URL set to 'module/static/'
STATIC_ROOT set to '/module/static_files/' (i read somewhere that they should not be the same)
and my uwsgi.ini looks like this:
[uwsgi]
module=Module.wsgi:application
master=True
http=:80
processes=4
threads=2
static-map /static= /module/static_files/
the projects file structure is set up in the following way:
-- Project:
---init.py
---settings.py
---urls.py
---wsgi.py
-- Logs
-- module
---static
---static_files
---[... module template, model, urls etc]
-manage.py
-db.sqlite3
I can run collectstatic and generate all the static files in the correct folder.
But when i run the uwsgi script, it wont work and gives me a 404 file not found for all static files.
I would really appreciate any help, I've been stuck on this for an entire week now...
(i have checked out Deployment with Django and Uwsgi
but as far as i can tell, my static-map is set correctly)
you need to add your static files as static-map=/static=/module/static_files/

Still having issues deploying flask app on Godaddy shared hosting

I've been trying now for some time to deploy my flask app on a Godaddy hosting server. I have done extensive searches online and followed them but I'm still having issues. Right now my app is just displaying as ordinary html so I'm having things like {{my_var}} displayed on the page. My flask app works locally and this is the folder structure;
myApp folder, which contains static folder for css,javascript, and images, templates folder for my html, and the myapp.py and forms.py files come under the myApp folder
On my hosting server my folder structure is currently this; $HOME/public_html which contains the index.html and base.html (index.html inherits from this file for the header and footers), $HOME/public_html/cgi-bin which contains myapp.cgi, myapp.py, and .htaccess files.
I've created a cgi file and made it executable which is saved in the public_html/cgi-bin folder. The file is also made executable with 755 permission. These are the contents;
#!/home/username/public_html/cgi-bin/flask_app/bin/python
from wsgiref.handlers import CGIHandler
from myapp import app
import os
import cgitb; cgitb.enable()
os.environ["SERVER_NAME"] = "127.0.0.1"
os.environ["SERVER_PORT"] = "4000"
os.environ["REQUEST_METHOD"] = "GET"
os.environ["SERVER_PROTOCOL"] = "http/1.1"
CGIHandler().run(app)
Note the shebang on my files is the path to my virtualenv where I have flask installed. The version of python is v2.7
I also have my main flask app (myapp.py which is also executable and with 755 permissions) file with the routes and the contents are as follows;
#!/home/username/public_html/cgi-bin/flask_app/bin/python
import os
import sys
sys.path.insert(0, '/home/aofadero/public_html/cgi-bin')#path to myapp.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def home():
return render_template("index.html")
if __name__ == "__main__":
app.run()
This file is also in my public_html/cgi-bin folder. I also have a .htaccess file which has the following content;
AddHandler cgi-script .cgi .py
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(/home/username/public_html/cgi-bin/myapp.cgi)
RewriteRule ^(.*)$ /home/username/public_html/cgi-bin/myapp.cgi/$1 [L]
Now this .htaccess file is currently in my public_html/cgi-bin folder because if I place it in public_html folder, I get a 500 error message. The only time I don't get the error is when the .htaccess file is in the cgi-bin folder. Some of the research I've done say to place it in the cgi-bin folder, others say in the public_html folder. I find that it only works for me when it's in the cgi-bin folder. If I do ./myapp.cgi I get the following error;
Status: 404 NOT FOUND
Content-Type: text/html
Content-Length: 233
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>...
Can anyone help me please because I've tried about everything I could on my own. Right now I'm just getting ordinary html and none of the flask components are showing. Thanks
I have similar problems. I understand that an index.htm file must be placed at public_html, but when you try to do render_template("index.htm"), Flask will look for this file in the templates folder. The rendering is not actually executed. The index.htm file will always be displayed on the browser as a default page. Have you been able to find the solution ?
You don't need to include the Python script in the public_html. If you go to the Cpanel main page and search for Python. From there, you can create a Python app which will let you direct your website to run the Python script.
Application root = path to the folder your python is stored. I stored mine in a Python folder in the root of the private html.
Application url = what URL should you need to put into the browser to get that script.
Application startup file = The name of your Python script.
Application Entry point = The callable object in your Python script (in your case, it would be app).
Please see the video here for a walkthrough of this process: https://www.youtube.com/watch?v=xFxL7Mvut6g&ab_channel=Hob-iZadeAdemEfendi

What is the ideal directory structure for Django deployed app on openshift?

I am successfully deploy my application in open shift with first hello message but now
I want an ideal directory structure for deploy on openshift this Thanks
Check the django-example repo from Openshift. You have an example project from where you can get the project structure.
project
appname-1/
appname-2/
appname-n/
static/ # to store your static files
project/
wsgi.py # file created by django-admin startproject
templates/
wsgi/
static/ # in your settings.py set this folder as your STATIC_ROOT
manage.py
setup.py # file created by openshift python cartridge
wsgi.py # file created by openshift python cartridge
When you do a git push to your openshift remote, all of these files and folders will be created in $OPENSHIFT_REPO_DIR. The special folder $OPENSHIFT_REPO_DIR/wsgi/static is used to bypass wsgi and serve the files directly using apache. For this reason you must set this folder as your STATIC_ROOT to collect all of your static files.
Also for storing user uploaded files you should create a folder under $OPENSHIFT_DATA_DIR. For example, $OPENSHIFT_DATA_DIR/media. This folder will be persisted across future deploys.
If you use sqlite3 for you database your settings should be:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(os.getenv($OPENSHIFT_DATA_DIR), 'media'),
}
}

Django and django oscar

Location of django:
/usr/lib/python2.7/dist-packages/django/__init__.pyc
Location of django oscar:
/usr/local/lib/python2.7/dist-packages/oscar/__init__.pyc
My static files are not getting served properly. Above is my production setting. On my local machine, the locations are:
/usr/local/lib/python2.7/dist-packages/oscar/__init__.pyc
/usr/lib/python2.7/dist-packages/django/__init__.pyc
Could this be a possible reason for above problem?
Oscar ships its own set of static files in oscar/static/oscar When you deploy your site, you should run manage.py collectstatic so these files are also collected in your STATIC_ROOT
On DigitalOcean's Django app, your Nginx configuration is located in /etc/nginx/sites-enabled/django You may need to update the following section to point to the location of your STATIC_ROOT
# your Django project's static files - amend as required
location /static {
alias /home/django/django_project/django_project/static;
}

Categories

Resources