Skip to content

Instantly share code, notes, and snippets.

@MySecondLanguage
Forked from genomics-geek/README.md
Created September 14, 2019 04:54
Show Gist options
  • Select an option

  • Save MySecondLanguage/d97dd3310c7fbe518f7af373cd7f5753 to your computer and use it in GitHub Desktop.

Select an option

Save MySecondLanguage/d97dd3310c7fbe518f7af373cd7f5753 to your computer and use it in GitHub Desktop.

Revisions

  1. @genomics-geek genomics-geek revised this gist Apr 26, 2017. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    # Guide on how to create and set up a Dockerized web app using Django REST APIs and ReactJS
    Hopefully this will answer *"How do I setup or start a Django project using REST Framework and ReactJS?"*

    This is a guide to show you step by step how this can be setup. If you just want to get started, use the cookiecuter I set up [cookiecutter-django-reactjs](https://github.com/genomics-geek/cookiecutter-django-reactjs). It basically is a fork of pydanny's cookiecutter, just added the front-end stuff :).

    I created this because it was __SUCH__ a pain in the ass setting up a project using all the latest technologies.
    After some research, I figured it out and have it working. The repo that implements this is located [here](https://github.com/genomics-geek/django_reactjs_boilerplate). Feel free to use it as a boilerplate ;)

  2. @genomics-geek genomics-geek revised this gist Apr 15, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Step08.md
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ npm init
    ## Install webpack packages

    ```
    npm install --save-dev webpack webpack-dev-server webpack-bundle-tracker
    npm install --save-dev webpack@1 webpack-dev-server@1 webpack-bundle-tracker
    ```

    ## Install babel compiler and plugins
    @@ -30,7 +30,7 @@ npm install --save-dev axios lodash

    ```
    npm install --save react react-dom
    npm install --save-dev redux redux-logger redux-thunk react-bootstrap react-fontawesome react-redux react-router react-router-redux react-cookie
    npm install --save-dev redux redux-logger redux-thunk prop-types react-bootstrap react-fontawesome react-redux react-router@3 react-router-redux@4 react-cookie
    ```

    ## Install React Hot Reloader 3 and associated plugins
  3. @genomics-geek genomics-geek revised this gist Apr 15, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Step08.md
    Original file line number Diff line number Diff line change
    @@ -30,7 +30,7 @@ npm install --save-dev axios lodash

    ```
    npm install --save react react-dom
    npm install --save-dev redux redux-thunk react-bootstrap react-fontawesome react-redux react-router react-router-redux react-cookie
    npm install --save-dev redux redux-logger redux-thunk react-bootstrap react-fontawesome react-redux react-router react-router-redux react-cookie
    ```

    ## Install React Hot Reloader 3 and associated plugins
    @@ -48,5 +48,5 @@ npm install --save-dev karma mocha expect deepfreeze karma-mocha karma-webpack k
    ## Install ESLint

    ```
    npm install --save-dev eslint eslint-plugin-import eslint-plugin-jsx-a11y@^2.2.3 eslint-plugin-react eslint-config-airbnb babel-eslint
    npm install --save-dev eslint eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react eslint-config-airbnb babel-eslint
    ```
  4. @genomics-geek genomics-geek revised this gist Feb 27, 2017. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions Step04.md
    Original file line number Diff line number Diff line change
    @@ -18,6 +18,7 @@ CREATE USER django WITH PASSWORD '[password]';
    ALTER ROLE django SET client_encoding TO 'utf8';
    ALTER ROLE django SET default_transaction_isolation TO 'read committed';
    ALTER ROLE django SET timezone TO 'UTC';
    ALTER USER django CREATEDB;
    ```

    ### Create a database for this specific Django project
  5. @genomics-geek genomics-geek revised this gist Jan 4, 2017. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion Step07.md
    Original file line number Diff line number Diff line change
    @@ -511,7 +511,6 @@ from django.conf.urls import include, url
    from django.contrib import admin
    from django.views.generic import TemplateView
    from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token
    from .views import AppView

    urlpatterns = [
    url(r'^$', TemplateView.as_view(template_name="index.html")),
  6. @genomics-geek genomics-geek revised this gist Jan 4, 2017. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions Step03.md
    Original file line number Diff line number Diff line change
    @@ -45,6 +45,13 @@ indent_size = 2

    [Flake8](https://flake8.readthedocs.io/en/latest/) is a is a wrapper around these tools: PyFlakes. pep8. It is a linting utility for Python. When used together with [Atom](https://atom.io/), [Atom Linter Plugin](https://atom.io/packages/linter) and [Atom Flake8 Plugin](https://atom.io/packages/flake8), this will mark source code that doesn't conform to settings in `.flake8` file.

    Example `.flake8` file:

    ```
    [flake8]
    max-line-length = 125
    ```

    ## ESLint

    The pluggable linting utility (tool to verify code quality) for JavaScript and JSX. When used together with [Atom](https://atom.io/), [Atom Linter Plugin](https://atom.io/packages/linter) and [Atom ESLint Plugin](https://atom.io/packages/linter-eslint), this will mark mark source code that doesn't conform to settings in `.eslintrc` file.
  7. @genomics-geek genomics-geek revised this gist Jan 4, 2017. 1 changed file with 9 additions and 8 deletions.
    17 changes: 9 additions & 8 deletions Step06.md
    Original file line number Diff line number Diff line change
    @@ -10,26 +10,27 @@ mkdir requirements

    ```
    # Django
    django==1.10.2
    django==1.10.4
    # Configuration
    dj-database-url==0.4.1
    python-decouple==3.0
    whitenoise==3.2.2
    # Django 3rd party modules
    django-allauth==0.28.0
    django-allauth==0.30.0
    django-extensions==1.7.5
    django-model-utils==2.6
    django-rest-auth==0.8.1
    django-webpack-loader==0.3.3
    djangorestframework==3.5.1
    djangorestframework-jwt==1.8.0
    django-rest-auth==0.9.0
    django-webpack-loader==0.4.1
    djangorestframework==3.5.3
    djangorestframework-jwt==1.9.0
    # Python-PostgreSQL Database Adapter
    psycopg2==2.6.2
    # Time zones support
    pytz==2016.7
    pytz==2016.10
    ```

    ## Local environment Python requirements - `./requirements/local.txt`
    @@ -56,7 +57,7 @@ flake8==3.2.1
    gunicorn==19.6.0
    # Email backend
    django-anymail==0.5
    django-anymail==0.7
    ```

    ## Install Local Python requirements
  8. @genomics-geek genomics-geek revised this gist Jan 4, 2017. 2 changed files with 5 additions and 1 deletion.
    4 changes: 4 additions & 0 deletions Step03.md
    Original file line number Diff line number Diff line change
    @@ -41,6 +41,10 @@ indent_style = space
    indent_size = 2
    ```

    ## Flake8

    [Flake8](https://flake8.readthedocs.io/en/latest/) is a is a wrapper around these tools: PyFlakes. pep8. It is a linting utility for Python. When used together with [Atom](https://atom.io/), [Atom Linter Plugin](https://atom.io/packages/linter) and [Atom Flake8 Plugin](https://atom.io/packages/flake8), this will mark source code that doesn't conform to settings in `.flake8` file.

    ## ESLint

    The pluggable linting utility (tool to verify code quality) for JavaScript and JSX. When used together with [Atom](https://atom.io/), [Atom Linter Plugin](https://atom.io/packages/linter) and [Atom ESLint Plugin](https://atom.io/packages/linter-eslint), this will mark mark source code that doesn't conform to settings in `.eslintrc` file.
    2 changes: 1 addition & 1 deletion Step06.md
    Original file line number Diff line number Diff line change
    @@ -42,7 +42,7 @@ pytz==2016.7
    django-debug-toolbar==1.6
    # Code linter
    pep8==1.7.0
    flake8==3.2.1
    ```

    ## Production environment Python requirements - `./requirements/production.txt`
  9. @genomics-geek genomics-geek revised this gist Dec 6, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Step08.md
    Original file line number Diff line number Diff line change
    @@ -36,7 +36,7 @@ npm install --save-dev redux redux-thunk react-bootstrap react-fontawesome react
    ## Install React Hot Reloader 3 and associated plugins

    ```
    npm install --save-dev react-hot-loader redux-devtools redux-devtools-dock-monitor redux-devtools-log-monitor
    npm install --save-dev react-hot-loader@next redux-devtools redux-devtools-dock-monitor redux-devtools-log-monitor
    ```

    ## Install Unit Testing packages
  10. @genomics-geek genomics-geek revised this gist Dec 5, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Step08.md
    Original file line number Diff line number Diff line change
    @@ -48,5 +48,5 @@ npm install --save-dev karma mocha expect deepfreeze karma-mocha karma-webpack k
    ## Install ESLint

    ```
    npm install --save-dev eslint eslint-plugin-import@^1.16.0 eslint-plugin-jsx-a11y eslint-plugin-react eslint-config-airbnb babel-eslint
    npm install --save-dev eslint eslint-plugin-import eslint-plugin-jsx-a11y@^2.2.3 eslint-plugin-react eslint-config-airbnb babel-eslint
    ```
  11. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 2 additions and 3 deletions.
    5 changes: 2 additions & 3 deletions Step03.md
    Original file line number Diff line number Diff line change
    @@ -70,12 +70,11 @@ Example `.eslintrc` file:
    "no-var": 0,
    "vars-on-top": 0,
    "comma-dangle": 0,
    "arrow-body-style": ["error", "always"],
    "arrow-body-style": ["error", "as-needed"],
    "import/no-extraneous-dependencies": ["error", {"devDependencies": true}],
    "max-len": ["error", { "comments": 120, "code": 120 }],
    "no-console": ["error", { "allow": ["warn", "error"] }],
    "no-unused-expressions": ["error", { "allowShortCircuit": true }],
    "arrow-body-style": ["error", "as-needed"]
    "no-unused-expressions": ["error", { "allowShortCircuit": true }]
    },
    "plugins": [
    "react"
  12. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 2 changed files with 4 additions and 4 deletions.
    4 changes: 2 additions & 2 deletions Step07.md
    Original file line number Diff line number Diff line change
    @@ -289,7 +289,7 @@ from .base import *

    WEBPACK_LOADER = {
    'DEFAULT': {
    'BUNDLE_DIR_NAME': 'js/builds-dev/',
    'BUNDLE_DIR_NAME': 'builds-dev/',
    'STATS_FILE': os.path.join(BASE_DIR, 'webpack', 'webpack-stats.dev.json')
    }
    }
    @@ -321,7 +321,7 @@ from .base import *

    WEBPACK_LOADER = {
    'DEFAULT': {
    'BUNDLE_DIR_NAME': 'js/builds/',
    'BUNDLE_DIR_NAME': 'builds/',
    'STATS_FILE': os.path.join(BASE_DIR, 'webpack', 'webpack-stats.production.json')
    }
    }
    4 changes: 2 additions & 2 deletions Step09.md
    Original file line number Diff line number Diff line change
    @@ -54,7 +54,7 @@ config.entry = {

    config.devtool = 'inline-sourcemap';
    config.output = {
    path: path.join(__dirname, '../static/js/builds-development/'),
    path: path.join(__dirname, '../static/builds-development/'),
    filename: '[name]-[hash].js',
    publicPath: 'http://0.0.0.0:3000/static/builds/',
    };
    @@ -99,7 +99,7 @@ config.entry = {
    };

    config.output = {
    path: path.join(__dirname, '../static/js/builds/'),
    path: path.join(__dirname, '../static/builds/'),
    filename: '[name]-[hash].min.js',
    publicPath: '/static/js/builds/'
    };
  13. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Step09.md
    Original file line number Diff line number Diff line change
    @@ -127,7 +127,7 @@ module.exports = config;

    ```
    mkdir -p static/js/src/main
    mkdir -p static/js/builds
    mkdir -p static/js/builds-development
    mkdir -p static/builds
    mkdir -p static/builds-development
    touch static/js/src/main/index.jsx
    ```
  14. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions Step07.md
    Original file line number Diff line number Diff line change
    @@ -510,11 +510,16 @@ from django.conf import settings
    from django.conf.urls import include, url
    from django.contrib import admin
    from django.views.generic import TemplateView
    from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token
    from .views import AppView

    urlpatterns = [
    url(r'^$', TemplateView.as_view(template_name="index.html")),
    url(r'^rest-auth/', include('rest_auth.urls')),
    url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
    url(r'^api-token-auth/', obtain_jwt_token),
    url(r'^api-token-refresh/', refresh_jwt_token),
    url(r'^api-token-verify/', verify_jwt_token),
    url(r'^admin/', admin.site.urls),
    ]

  15. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions Step07.md
    Original file line number Diff line number Diff line change
    @@ -31,6 +31,7 @@ For the full list of settings and their values, see
    https://docs.djangoproject.com/en/1.10/ref/settings/
    """

    import datetime
    import dj_database_url
    import os

    @@ -90,6 +91,7 @@ THIRD_PARTY_APPS = [
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',
    'rest_auth.registration',
    'webpack_loader',
    ]

    @@ -250,9 +252,15 @@ REST_FRAMEWORK = {
    # Django REST-AUTH framework
    # ------------------------------------------------------------------------------
    # https://github.com/Tivix/django-rest-auth/
    # https://github.com/GetBlimp/django-rest-framework-jwt

    REST_USE_JWT = True

    JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1),
    'JWT_ALLOW_REFRESH': True,
    }


    # EMAIL CONFIGURATION
    # ------------------------------------------------------------------------------
  16. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Step03.md
    Original file line number Diff line number Diff line change
    @@ -73,7 +73,7 @@ Example `.eslintrc` file:
    "arrow-body-style": ["error", "always"],
    "import/no-extraneous-dependencies": ["error", {"devDependencies": true}],
    "max-len": ["error", { "comments": 120, "code": 120 }],
    "no-console": ["error", { allow: ["warn", "error"] }],
    "no-console": ["error", { "allow": ["warn", "error"] }],
    "no-unused-expressions": ["error", { "allowShortCircuit": true }],
    "arrow-body-style": ["error", "as-needed"]
    },
  17. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion Step03.md
    Original file line number Diff line number Diff line change
    @@ -72,7 +72,10 @@ Example `.eslintrc` file:
    "comma-dangle": 0,
    "arrow-body-style": ["error", "always"],
    "import/no-extraneous-dependencies": ["error", {"devDependencies": true}],
    "max-len": ["error", { "comments": 120, "code": 120 }]
    "max-len": ["error", { "comments": 120, "code": 120 }],
    "no-console": ["error", { allow: ["warn", "error"] }],
    "no-unused-expressions": ["error", { "allowShortCircuit": true }],
    "arrow-body-style": ["error", "as-needed"]
    },
    "plugins": [
    "react"
  18. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions Step10.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    # Wire up Django/ReactJS application

    __NOTE__: I have made some changes to this. I wanted to include the redux-dev-tools library. Refer to this [commit](https://github.com/genomics-geek/django_reactjs_boilerplate/commit/38dd16caea3a96ed788535769794bc265402e89f) to see the changes.

    In this step, we will make sure Django and ReactJS are communicating. We will now be able to use Django as our backend server and ReactJS to handle all of the frontend.

    ## Write placeholder React Component
  19. @genomics-geek genomics-geek revised this gist Oct 30, 2016. No changes.
  20. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions Step09.md
    Original file line number Diff line number Diff line change
    @@ -65,6 +65,7 @@ config.plugins = [
    new webpack.DefinePlugin({
    'process.env': {
    NODE_ENV: JSON.stringify('development'),
    BASE_URL: JSON.stringify('http://0.0.0.0:8000/'),
    }
    })
    ];
    @@ -110,6 +111,7 @@ config.plugins = [
    new webpack.DefinePlugin({
    'process.env': {
    NODE_ENV: JSON.stringify('production'),
    BASE_URL: JSON.stringify('http://0.0.0.0/'),
    }
    }),
    new webpack.optimize.UglifyJsPlugin({
  21. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions Step14.md
    Original file line number Diff line number Diff line change
    @@ -17,6 +17,7 @@ mkdir -p static/js/src/utilities/
    We will use the react-cookie library (Makes this so easy!). We will use Cross-Site Request Forgery (CSRF) token and JSON web token (JWT) to secure our application.

    It will make our application safe against Cross-site scripting (XSS) and CSRF attacks by following these strategies:

    1. Store JWT in a httpOnly and secure cookie
    2. Use a CSRF token with any methods that alter data on the server (PUT, POST, DELETE, PATCH).
    3. GET should __NOT__ cause changes server side. This is reserved for PUT, POST, DELETE, PATCH methods.
  22. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 2 changed files with 84 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -33,4 +33,5 @@ Main features:
    ## 10. [Wire up Django/ReactJS application](https://gist.github.com/genomics-geek/98929a9e7ba9602fed7bfa4a5a1c5c4e#file-step10-md)
    ## 11. [Setup Karma and Mocha for running JavaScript Unittests](https://gist.github.com/genomics-geek/98929a9e7ba9602fed7bfa4a5a1c5c4e#file-step11-md)
    ## 12. [Customize NodeJS commands for ease of use](https://gist.github.com/genomics-geek/98929a9e7ba9602fed7bfa4a5a1c5c4e#file-step12-md)
    ## 13. [Dockerize application](https://gist.github.com/genomics-geek/98929a9e7ba9602fed7bfa4a5a1c5c4e#file-step13-md)
    ## 13. [Dockerize application](https://gist.github.com/genomics-geek/98929a9e7ba9602fed7bfa4a5a1c5c4e#file-step13-md)
    ## 14. [Add Helpful Utilities for Consuming Django APIs with React](https://gist.github.com/genomics-geek/98929a9e7ba9602fed7bfa4a5a1c5c4e#file-step14-md)
    82 changes: 82 additions & 0 deletions Step14.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,82 @@
    # Helpful utilities for dealing with Django APIs with React

    We will create helpful utilities to consume APIsin a secure fashion. We will use the following libraries:
    + react-cookie
    + axios

    ## Front-end utilities

    ### 1. Create `utilities` directory

    ```
    mkdir -p static/js/src/utilities/
    ```

    ### 2. Create script to interact with application cookie

    We will use the react-cookie library (Makes this so easy!). We will use Cross-Site Request Forgery (CSRF) token and JSON web token (JWT) to secure our application.

    It will make our application safe against Cross-site scripting (XSS) and CSRF attacks by following these strategies:
    1. Store JWT in a httpOnly and secure cookie
    2. Use a CSRF token with any methods that alter data on the server (PUT, POST, DELETE, PATCH).
    3. GET should __NOT__ cause changes server side. This is reserved for PUT, POST, DELETE, PATCH methods.

    Create the `static/js/src/utilities/cookie.js` file. It should look like this:

    ```javascript
    import cookies from 'react-cookie';


    // This is the place where we can load elements from a cookie to be used in our app

    // Django CRSF Token is stored in a cookie
    const csrftoken = cookies.load('csrftoken');

    // JWT is going to be saved into cookie
    // cookies.save('jwt', response.data.token, { secure: true, httpOnly: true });
    // Therefore it will automatically be sent in the header of all API requests
    // JWT will NOT be accessible to JavaScript because it is httpOnly :)

    export { csrftoken };
    ```

    ### 3. Create script to use to interact with Django APIs

    We will use the axios library to set this up. Create the `static/js/src/utilities/api.js` file. It should look like this:

    ```javascript
    import axios from 'axios';
    import * as cookie from './cookie';


    const api = axios.create({
    baseURL: process.env.BASE_URL,
    timeout: 1000,
    });

    // CRSF token is needed in all requests that can make a change server side
    api.defaults.headers.post['X-CSRFToken'] = cookie.csrftoken;
    api.defaults.headers.put['X-CSRFToken'] = cookie.csrftoken;
    api.defaults.headers.patch['X-CSRFToken'] = cookie.csrftoken;
    // api.defaults.headers.delete['X-CSRFToken'] = cookie.csrftoken; // Currently axios can't set headers for DELETE

    // Since we will only be using JSON APIs, add Content-Type: application/json to header as default
    api.defaults.headers.post['Content-Type'] = 'application/json';
    api.defaults.headers.put['Content-Type'] = 'application/json';
    api.defaults.headers.patch['Content-Type'] = 'application/json';

    // Since we will only be using JSON APIs, add Accept: application/json to header as default
    api.defaults.headers.get.Accept = 'application/json';
    api.defaults.headers.post.Accept = 'application/json';
    api.defaults.headers.put.Accept = 'application/json';
    api.defaults.headers.patch.Accept = 'application/json';

    // JWT is going to be saved into cookie
    // cookies.save('jwt', response.data.token, { secure: true, httpOnly: true });
    // Therefore it will automatically be sent in the header of all API requests
    // JWT will not be accessible to JavaScript because it is httpOnly :)

    export default api;
    ```

    __NOTE:__ Currently axios does not allow setting headers on DELETE method. I raised this [issue](https://github.com/mzabriskie/axios/issues/509) and it should be included in the next release.
  23. @genomics-geek genomics-geek revised this gist Oct 30, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Step08.md
    Original file line number Diff line number Diff line change
    @@ -30,7 +30,7 @@ npm install --save-dev axios lodash

    ```
    npm install --save react react-dom
    npm install --save-dev redux redux-thunk react react-dom react-bootstrap react-fontawesome react-redux react-router react-router-redux
    npm install --save-dev redux redux-thunk react-bootstrap react-fontawesome react-redux react-router react-router-redux react-cookie
    ```

    ## Install React Hot Reloader 3 and associated plugins
  24. @genomics-geek genomics-geek revised this gist Oct 27, 2016. 1 changed file with 0 additions and 4 deletions.
    4 changes: 0 additions & 4 deletions Step07.md
    Original file line number Diff line number Diff line change
    @@ -254,10 +254,6 @@ REST_FRAMEWORK = {
    REST_USE_JWT = True


    # EMAIL CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/topics/email/

    # EMAIL CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/topics/email/
  25. @genomics-geek genomics-geek revised this gist Oct 27, 2016. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions Step09.md
    Original file line number Diff line number Diff line change
    @@ -107,6 +107,11 @@ config.plugins = [
    new BundleTracker({ filename: './webpack/webpack-stats.production.json' }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.DefinePlugin({
    'process.env': {
    NODE_ENV: JSON.stringify('production'),
    }
    }),
    new webpack.optimize.UglifyJsPlugin({
    mangle: false,
    sourcemap: false
  26. @genomics-geek genomics-geek revised this gist Oct 27, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Step10.md
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,7 @@ ReactDOM.render(
    <AppContainer>
    <HelloWorld />
    </AppContainer>,
    document.getElementById('app-root')
    document.getElementById('react-root')
    );

    if (module.hot) {
  27. @genomics-geek genomics-geek revised this gist Oct 27, 2016. 1 changed file with 0 additions and 4 deletions.
    4 changes: 0 additions & 4 deletions Step11.md
    Original file line number Diff line number Diff line change
    @@ -77,10 +77,6 @@ module.exports = function (config) {

    We set this up with an example test because if not Karma will complain ;)

    ```
    mkdir -p static/js/tests/examples
    ```

    `static/js/src/test_index.js`:
    ```javascript
    var testsContext = require.context('.', true, /.spec$/);
  28. @genomics-geek genomics-geek revised this gist Oct 27, 2016. 1 changed file with 14 additions and 3 deletions.
    17 changes: 14 additions & 3 deletions Step10.md
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,7 @@ const HelloWorld = () => {
    export default HelloWorld;
    ```

    `./static/js/src/index.jsx` should look like this:
    `./static/js/src/main/index.jsx` should look like this:
    ```javascript
    import React from 'react';
    import ReactDOM from 'react-dom';
    @@ -44,7 +44,7 @@ if (module.hot) {
    <AppContainer>
    <HelloWorld />
    </AppContainer>,
    document.getElementById('app-root')
    document.getElementById('react-root')
    );
    });
    }
    @@ -53,7 +53,18 @@ if (module.hot) {
    ## Update HTML template to enable hot reloading

    We need to tell the Django template to load the latest javascript bundle. Because we are using Django webpack loader, we can enable hot reloading during development ;).
    Add the following in the javascript block in the template:
    The `index.html` page should now look like this:

    ```
    {% extends 'base.html' %}
    {% load staticfiles %}
    {% load render_bundle from webpack_loader %}
    {% block body %}
    <div id="react-root"></div>
    {% endblock body %}
    {% block javascript %}
    {% render_bundle 'main' %}
    {% endblock javascript %}
    ```
  29. @genomics-geek genomics-geek revised this gist Oct 27, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Step09.md
    Original file line number Diff line number Diff line change
    @@ -119,7 +119,7 @@ module.exports = config;
    ## Create the entry point for our front-end project

    ```
    mkdir -p static/js/src
    mkdir -p static/js/src/main
    mkdir -p static/js/builds
    mkdir -p static/js/builds-development
    touch static/js/src/main/index.jsx
  30. @genomics-geek genomics-geek revised this gist Oct 27, 2016. 1 changed file with 380 additions and 1 deletion.
    381 changes: 380 additions & 1 deletion Step07.md
    Original file line number Diff line number Diff line change
    @@ -19,19 +19,398 @@ mv django_config/settings.py django_config/settings/base.py
    ## Configure Base Django settings - `./django_configs/settings/base.py`

    ```python
    """
    Django settings for django_config project.
    Generated by 'django-admin startproject' using Django 1.10.2.
    For more information on this file, see
    https://docs.djangoproject.com/en/1.10/topics/settings/
    For the full list of settings and their values, see
    https://docs.djangoproject.com/en/1.10/ref/settings/
    """

    import dj_database_url
    import os

    from decouple import config


    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    APPS_DIR = os.path.join(BASE_DIR, 'django_apps')


    # SECRET KEY
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-SECRET_KEY
    # SECURITY WARNING: keep the secret key used in production secret!

    SECRET_KEY = config('SECRET_KEY')


    # DEBUG
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/ref/settings/#debug
    # SECURITY WARNING: don't run with debug turned on in production!

    DEBUG = config('DEBUG', cast=bool)


    # MANAGER CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/ref/settings/#admins
    # https://docs.djangoproject.com/en/1.10/ref/settings/#managers

    ADMINS = (
    ("""Michael A. Gonzalez""", 'GonzalezMA.CHOP@gmail.com'),
    )

    MANAGERS = ADMINS


    # APP CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/ref/settings/#installed-apps

    DJANGO_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    ]

    THIRD_PARTY_APPS = [
    'allauth',
    'allauth.account',
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',
    'webpack_loader',
    ]

    LOCAL_APPS = []

    INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS


    # MIDDLEWARE CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/topics/http/middleware/

    DJANGO_SECURITY_MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    ]

    DJANGO_MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    MIDDLEWARE = DJANGO_SECURITY_MIDDLEWARE + DJANGO_MIDDLEWARE


    # URL Configuration
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/ref/settings/#root-urlconf

    ROOT_URLCONF = 'django_config.urls'


    # TEMPLATE CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/topics/templates/

    TEMPLATES = [
    {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(APPS_DIR, 'templates')],
    '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',
    ],
    },
    },
    ]


    # WGSI CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/ref/settings/#wsgi-application

    WSGI_APPLICATION = 'django_config.wsgi.application'


    # DATABASE CONFIGURATION
    # ------------------------------------------------------------------------------
    # See: https://docs.djangoproject.com/en/1.10/ref/settings/#databases

    DATABASES = {
    'default': dj_database_url.parse(config('DATABASE_URL')),
    }
    DATABASES['default']['ATOMIC_REQUESTS'] = True

    # Added this to support deployment on Heroku
    # https://devcenter.heroku.com/articles/django-app-configuration
    db_from_env = dj_database_url.config(conn_max_age=500)
    DATABASES['default'].update(db_from_env)


    # PASSWORD VALIDATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

    AUTH_PASSWORD_VALIDATORS = [
    {
    'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
    'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
    'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
    'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
    ]


    # GENERAL CONFIGURATION
    # ------------------------------------------------------------------------------
    # Local time zone for this installation. Choices can be found here:
    # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
    # although not all choices may be available on all operating systems.
    # In a Windows environment this must be set to your system time zone.
    # https://docs.djangoproject.com/en/1.10/topics/i18n/

    LANGUAGE_CODE = 'en-us'

    TIME_ZONE = 'UTC'

    USE_I18N = True

    USE_L10N = True

    USE_TZ = True

    SITE_ID = 1


    # STATIC FILE CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/howto/static-files/

    STATIC_URL = '/static/'

    STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]

    STATIC_ROOT = os.path.join(BASE_DIR, 'static_cdn')


    # MEDIA CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/ref/settings/#media-root
    # https://docs.djangoproject.com/en/1.10/ref/settings/#media-url

    MEDIA_URL = "/media/"

    MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "media_cdn")


    # Django REST framework
    # ------------------------------------------------------------------------------
    # http://www.django-rest-framework.org/

    REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
    'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication',
    'rest_framework.authentication.TokenAuthentication',
    'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
    }


    # Django REST-AUTH framework
    # ------------------------------------------------------------------------------
    # https://github.com/Tivix/django-rest-auth/

    REST_USE_JWT = True


    # EMAIL CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/topics/email/

    # EMAIL CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/topics/email/

    EMAIL_PORT = config('EMAIL_PORT')

    EMAIL_HOST = config('EMAIL_HOST')

    EMAIL_BACKEND = config('EMAIL_BACKEND')

    DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL')
    ```

    ## Configure Local Django settings - `./django_configs/settings/local.py`

    ```python
    import socket

    from .base import *


    # Webpack Loader by Owais Lane
    # ------------------------------------------------------------------------------
    # https://github.com/owais/django-webpack-loader

    WEBPACK_LOADER = {
    'DEFAULT': {
    'BUNDLE_DIR_NAME': 'js/builds-dev/',
    'STATS_FILE': os.path.join(BASE_DIR, 'webpack', 'webpack-stats.dev.json')
    }
    }

    # Django Debug Toolbar
    # ------------------------------------------------------------------------------
    # https://github.com/jazzband/django-debug-toolbar

    MIDDLEWARE += ('debug_toolbar.middleware.DebugToolbarMiddleware',)

    INSTALLED_APPS += ('debug_toolbar', )

    INTERNAL_IPS = ['127.0.0.1', '10.0.2.2', ]

    # Hack to have debug toolbar when developing with docker
    ip = socket.gethostbyname(socket.gethostname())
    INTERNAL_IPS += [ip[:-1] + "1"]
    ```

    ## Configure Production Django settings - `./django_configs/settings/production.py`

    ```python

    from .base import *


    # Webpack Loader by Owais Lane
    # ------------------------------------------------------------------------------
    # https://github.com/owais/django-webpack-loader

    WEBPACK_LOADER = {
    'DEFAULT': {
    'BUNDLE_DIR_NAME': 'js/builds/',
    'STATS_FILE': os.path.join(BASE_DIR, 'webpack', 'webpack-stats.production.json')
    }
    }


    # Use Whitenoise to serve static files
    # ------------------------------------------------------------------------------
    # https://whitenoise.readthedocs.io/

    MIDDLEWARE = DJANGO_SECURITY_MIDDLEWARE + ['whitenoise.middleware.WhiteNoiseMiddleware'] + DJANGO_MIDDLEWARE

    STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'


    # Use Gunicorn as WSGI HTTP server
    # ------------------------------------------------------------------------------
    # http://gunicorn.org/

    INSTALLED_APPS += ('gunicorn', )


    # SITE CONFIGURATION
    # ------------------------------------------------------------------------------
    # Hosts/domain names that are valid for this site
    # See https://docs.djangoproject.com/en/1.6/ref/settings/#allowed-hosts

    ALLOWED_HOSTS = config(
    'ALLOWED_HOSTS',
    cast=lambda v: [d for d in [s.strip() for s in v.split(' ')] if d],
    default='',
    )


    # EMAIL CONFIGURATION - Anymail with Mailgun
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/1.10/topics/email/
    # https://github.com/anymail/django-anymail

    INSTALLED_APPS += ('anymail', )

    ANYMAIL = {
    'MAILGUN_API_KEY': config('MAILGUN_API_KEY'),
    }


    # LOGGING CONFIGURATION
    # ------------------------------------------------------------------------------
    # See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
    # A sample logging configuration. The only tangible logging
    # performed by this configuration is to send an email to
    # the site admins on every HTTP 500 error when DEBUG=False.
    # See http://docs.djangoproject.com/en/dev/topics/logging for
    # more details on how to customize your logging configuration.

    LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
    'require_debug_false': {
    '()': 'django.utils.log.RequireDebugFalse'
    }
    },
    'formatters': {
    'verbose': {
    'format': '%(levelname)s %(asctime)s %(module)s '
    '%(process)d %(thread)d %(message)s'
    },
    },
    'handlers': {
    'mail_admins': {
    'level': 'ERROR',
    'filters': ['require_debug_false'],
    'class': 'django.utils.log.AdminEmailHandler'
    },
    'console': {
    'level': 'DEBUG',
    'class': 'logging.StreamHandler',
    'formatter': 'verbose',
    },
    },
    'loggers': {
    'django.request': {
    'handlers': ['mail_admins'],
    'level': 'ERROR',
    'propagate': True
    },
    'django.security.DisallowedHost': {
    'level': 'ERROR',
    'handlers': ['console', 'mail_admins'],
    'propagate': True
    }
    }
    }
    ```

    ## Setup initial placeholder landing page