Setting up flask backend in AWS amplify - amazon-web-services

I want to setup flask backend in aws amplify, my frontend is react js.
Here is the folder structure:
root:
-flask-backend
--flask_app.py
--modules
-react-frontend
Note that my flask backend has app.py which is the core file and is supposed to backend listening to requests and then modules have some of the dependencies (imports) required to run app.py
The flow is like this:
react front end requests and fetches data from flask backend and accordingly the pages open. how to set it up? I referred to this medium article but nowhere it's shown how to configure backend based on your path (currently I have put my files in a git repository) so that both frontend and backend run parallely.

Related

django on heroku: celery worker gets 403 forbidden when accessing s3 media to read and process media files

I'm really stuck on this one because I'm not sure where to start:
My Django project allows users to upload a spreadsheet and the app then processes and aggregates the uploaded data.
The file is uploaded to the MEDIA_URL using a standard form and Django model with a FileField.
Once it's uploaded a celery worker accesses the file and processes it, writing the output to another model.
This works fine locally, but is not working in production. I'm deploying to heroku, and using the cookiecutter-django project template. I've set up an s3 bucket and am using the django-storages library.
The files upload without a problem - I can access and delete them in the Django admin, and also in the s3 bucket.
However when the celery worker tries to read the file, I get an HTTP Error 403: Forbidden.
I'm not sure how to approach this problem, because I am not sure which part of the stack contains my mistake. Could it be my tasks.py module, heroku:redis addon, or settings.py module?
It's necessary to tell celery where to get its configuration from (which settings file to use). I wasn't updating the config to production settings when deploying.
This is my fixed celery_app.py
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
app = Celery("<project_name>")
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object("django.conf:settings", namespace="CELERY")
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()

404 on any route for Flask app deployed to Elastic Beanstalk

I am trying to host a Flask app that implements a REST API using Flask-RESTful on Elastic Beanstalk through the eb cli. I have successfully deployed my application and I am not getting any error messages on my events log. I can successfully ssh into the instances and run the script to prepopulate my database and everything. But whenever I try to access any routes I keep getting a 404 error.
I initially assumed that it was because it wasn't finding my WSGIPath, so I changed the file name to application.py and updated the EBS software configuration to point to that file. I have also updated all instances of app to application in the codebase based on AWS documentation. Still nothing. Does anyone have any idea what could be wrong?
This is my application.py:
from flask import Flask
from config import Config
CONFIG = Config()
# AWS Elastic Beanstalk expects an `application` variable.
application = Flask(__name__)
if __name__ == "__main__":
# Importing these here to avoid issue with circular imports
from endpoints.v1.exports import exports_api
from endpoints.v1.imports import imports_api
application.register_blueprint(exports_api, url_prefix="/api/v1")
application.register_blueprint(imports_api, url_prefix="/api/v1")
application.run(debug=CONFIG.DEBUG)
Here is where the application.py file lies in the folder structure:
- project root
- ...
- application.py
- ...
Just realized what was going on. I was trying to register the blueprints inside of the if __name__ == "__main__": block. But since the application.py file is not run directly by Elastic Beanstalk, it was never reaching those lines and so the endpoints I was trying to hit didn't exist.
I had to refactor my code so I could move it outside of that block and avoid issues with circular imports, but now it's all working as it should.

How to connect existing Django app with existing react app using webpack

So I have a Django project that acts as a backend REST server, and I would like to integrate that with an existing React project that makes AJAX calls to this REST server. Again, both of these projects already exist, I just want to connect them. Let's say the root of my Django project is DJANGOROOT and that is where manage.py is located. My Django project has a couple of Django apps that are part of the project. Let's say my Django project is called "mydjangoproj", the two Django apps are called "myapp1" and "myapp2" and the React project is called "myreactproj". Each of these two projects (the Django project with the two apps, and the React project) is stored in a separate GIT repo and to connect them on my server I have the following directory structure:
DJANGOROOT/
DJANGOROOT/mydjangoproj
DJANGOROOT/mydjangoproj/settings.py
DJANGOROOT/mydjangoproj/urls.py
DJANGOROOT/mydjangoproj/static/
DJANGOROOT/mydjangoproj/templates/
DJANGOROOT/myapp1
DJANGOROOT/myapp2
DJANGOROOT/myreactproj
DJANGOROOT/myreactproj/package.json
DJANGOROOT/myreactproj/src
DJANGOROOT/myreactproj/src/index.js
etc
Note that the React app root folder is inside DJANGOROOT and is parallel to my django project and app folders.
The React app uses an npm module called react-scripts (see https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#npm-run-build) that has a build script that will build all the stuff in DJANGOROOT/myreactproj/src (staring with index.js) and will put all this in a folder called DJANGOROOT/myreactproj/build. When I run the build (using "npm run build") it fills up the folder DJANGOROOT/myreactproj/build like this:
DJANGOROOT/myreactproj/build
DJANGOROOT/myreactproj/build/index.html
DJANGOROOT/myreactproj/build/{several other files}
DJANGOROOT/myreactproj/build/static
DJANGOROOT/myreactproj/build/static/css
DJANGOROOT/myreactproj/build/static/js
DJANGOROOT/myreactproj/build/static/media
So it appears that to connect Django to my React app, I have to find a way to have the root path for Django (mydomain.com/) point to DJANGOROOT/myreactproj/build/index.html. I understand that I must create a "home" template that is launched by the Django view that runs at mydomain.com/, and that home template has to launch the React app something like this:
{% load render_bundle from webpack_loader %}
{% render_bundle 'main' 'js' 'DEFAULT' %}
But I'm not sure how exactly I need to tell Django where to look for main.js (or is it index.js) and I'm not sure how to get Django to see all the static stuff in DJANGOROOT/myreactproj/build/static.
I also ran "npm list webpack" inside DJANGOROOT/myreactproj to get the version of webpack, and it shows this:
└─┬ react-scripts#1.0.11
└── webpack#3.5.1
I assume this means that webpack 3.5.1 is being used and is somehow bundles with react-scripts v 1.0.11
Also note that the Django app is already running under HTTPS under NGINX and UWSGI, so this is a real server not a dev server.
Can someone who has been through this process shed some light on what I need to do to hook this all up properly?
If your react app is using django just to get data via REST, why you want to use react in django templates? I think preferred approach here is separation not integration. Create standalone react app with its own server (both can run on one physical server of course) - this way your react app and django app will communicate only by rest calls and nothing else needed. If you have some assets in django app - move them to frontend react app.

Putting Flask and Phonegap together

I have this app built with flask and now i'm trying to run it on my phone with phonegap.
Although the way i have it organized originally with flask is something like this:
/project
run-dev.py
config.py
/phonegapfolder
/app
user.py
forms.py
views.py
__init__.py
/templates
index.html
My problem comes from the fact that phonegap demands its main html to be the one in
/phonegapfolder/www/index.html
Of course it's useless to just copy my index.html from one folder from another, because we will not find the python files that lie within the app folder.
You best solution would be to use flask on a backend (remote) server and have the PhoneGap application make server requests to the flask server.
PhoneGap projects require that the index.html be set within the application (www) folder.
This post on Reddit might be able to clarify some of the details.

Client side JS (e.g. AngularJS) + Django REST Backend: Deploy onto single PaaS?

Basically I'm structuring my app similar to this GitHub project:
https://github.com/zackargyle/angularjs-django-rest-framework-seed
Is it possible to deploy both the backend and frontend onto a single PaaS such as Heroku/Elastic Beanstalk?
Having a separated REST backend and JavaScript frontend seems like a cleaner/more scalable way to do things rather than trying to mix them together like [django-angular]: (http://django-angular.readthedocs.org/en/latest/index.html/), or having a REST backend mix with the Django app like http://blog.mourafiq.com/post/55099429431/end-to-end-web-app-with-django-rest-framework
If it is not possible to deploy it easily onto Elastic Beanstalk, is there an easy way to deploy the Django backend onto Elastic Beanstalk, and AngularJS frontend to Amazon EC2/S3 with minimal configuration?
I realize there's a similar discussion before this: Client JS + Django Rest Framework
but it lacks more specific details.
I'm in the exact same boat with AngularJS as my client and django-rest-framework as my service. I also have the same type of git setup where the server and client code are siblings in the same repository. I don't have any experience with Heroku and I'm new to beanstalk but I was able to deploy my site and it's working on AWS beanstalk.
With beanstalk there are two ways I know of to deploy your code.
Use eb and git described here.
Works well if you want to push your source code directly.
Create your own zip to upload to beanstalk via the AWS management console. Amazon has a walkthrough on it here.
Route I chose so I can 'grunt build' my client and zip with server code before deploying.
I automated the zip creation using a python script. Amazon's walkthrough provides an example python zip. You have to structure it properly, mine looks roughly like this
app.zip
/.ebextensions/
/.elasticbeanstalk/
/app/ <-- my django-rest-framework project (settings.py, wsgi.py, etc.)
/restapi/ <-- my django-rest-framework application (my api)
/static/ <-- AngularJS results of 'grunt build' put here
/manage.py
/requirements.txt
I know you didn't specifically ask but the .config file inside .ebextensions/ took me way too long to get working. It can be formatted as YAML or JSON (can be confusing at first as every blog shows it differently). This blog helped me out quite a bit just be careful to use container_commands: and not commands:. I lost a few hours to that...
container_commands:
01_syncdb:
command: "django-admin.py syncdb --noinput"
leader_only: true
option_settings:
"aws:elasticbeanstalk:container:python:environment":
"DJANGO_SETTINGS_MODULE": "app.settings"
"aws:elasticbeanstalk:container:python":
"WSGIPath": "app/wsgi.py"
"StaticFiles": "/static/=static/"
"aws:elasticbeanstalk:container:python:staticfiles":
"/static/": "static/"
"aws:elasticbeanstalk:application:environment":
"AWS_SECRET_KEY": "<put your secret key here if you want to reference from env variable>"
"AWS_ACCESS_KEY_ID": "<put your access key here>"
"AWS_S3_Bucket": "<put your bucket here>"
In the zip you create (if you follow the beanstalk guides on django) the client code in your /static/ folder is automatically pushed to s3 when you deploy.
This setup isn't perfect and I plan on fine tuning things but it's working. Here are some downsides I ran into that I haven't solved yet:
Since I put my client code in the static/ folder my site sits under mysite.com/static/. Ideally I'd want it to be served as the root at mysite.com with my django-rest-framework content under mysite.com/api/
If you use the self describing api on beanstalk by default the assets won't be pushed since they sit in your python directory and not with your source code.
UPDATE 4-17-2014
I further refined this setup so I no longer have to go to mysite.com/static/ to load my index.html. To do so I used a django class based view to map index.html to the root of my site. My urls.py looks like
urlpatterns = patterns('',
(r'^$', TemplateView.as_view(template_name="index.html")),
...
)
and in my settings.py I configured TEMPLATE_DIRS as follows
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__) , '../static').replace('\\','/')
)
I use ../static because my static directory is a sibling of my app directory.
The last piece was to update my Gruntfile.js so 'grunt build' prefixes all the relative URLs in my angular code with the static folder. I used grunt-text-replace for this. It's the last task that runs after my code is sitting minified in a /dist folder. The downside to this approach is I'll have to update this task if I ever add static content to a new subfolder besides scripts, bower_components, styles, etc.
replace: {
replace_js_templates: {
src: ['dist/scripts/*.js'],
overwrite: true, // overwrite matched source files
replacements: [{
from: /templateUrl:\s*"/g,
to: 'templateUrl:"static/'
}]
},
replace_index: {
src: ['dist/index.html'],
overwrite: true, // overwrite matched source files
replacements: [{
from: /(src|href)="(bower_components|styles|scripts)/g,
to: '$1="static/$2'
}
]
}
},
Now django will serve my index.html page but everything else in my /static/ directory can benefit from a CDN.