Tumblelog by Soup.io
Newer posts are loading.
You are at the newest post.
Click here to check if anything new just came in.

December 28 2017

December 23 2017

December 20 2017

Building Modern Django Web Applications with React and Django Rest Framework

In nutshell, in this tutorial we'll look at how to build a modern (SPA: Single Page Application) CRUD web application using Django and React.js (instead of Django built-in templates engine). We'll use Django Rest Framework to build an example API, react-router-dom for routing the front-end app, Axios for making HTTP calls (GET, POST, PUT and DELETE etc.) to the Rest API endpoints, Redux for managing the app's global state and finally Webpack to bundle the assets

This tutorial will cover how to serve the React app using the Django server and how to allow the React app to communicate with the Django server over its Rest API endpoints

When building a modern web application with tools such as Django and React in our case, React will take care of rendering the view layer of your app's architecure and Django will be used for communicating with the database and exposing a CRUD REST API. You can have completly separate front-end and back-end or you can also make Django serve the first page where the React app will be mounted (we'll follow this second approach in this tutorial).

The communication between React and Django will be made using HTTP/Ajax requests to the rest API endpoints (we'll use Axios but you can also use the modern browser's fetch API or even the old XMLHttpRequest interface or a wrapper library around it).

We'll use the modern front-end tools such as Webpack and Babel for transpiling (compiling from JavaScript 2015 (ES6) to JavaScript 5) and bundling React source code into one single bundle. Don't worry though, we'll be using create-react-app, an official React CLI-based tool that allows you to generate and locally serve React projects (among other features) without going through the hassle of Webpack configuration or any complex JavaScript configuration.

In the back-end we'll create a simple Django API with Django Rest Framework.

In the front-end we'll consume the API (with Axios and Promises) to fetch data and then render it. We'll also add routing using the React router version 4 and Redux for managing the global state of the application.

Setting Up the Development Environment

This tutorial assumes you have a development environment with Python and NodeJS installed. You can find the binaries and the instructions to install both platforms on their corresponding official websites.

It's recommended that you use python virtualenv. A tool that allows you to create isolated virtual environments for Python packages so you can install and use different versions of the same library (for different projects) and avoid any conflicts. You can install virtualenv using the virtualenvwrapper.

Installing Django

First, let's start by creating and activating a new virtual environment for our project dependencies:

virtualenv myenv
source myenv/bin/activate

Next you'll need to install Django using the pip package manager:

pip install django

Creating a Django Project

After installing Django, you'll be able to create a Django project using django-admin

django-admin startproject django-react-crud

If you migrate your database and serve your app, at this point, with:

python manage.py migrate
python manage.py runserver

You should have the famous It Worked! welcome page when you navigate with your web browser to http://127.0.0.1:8000.

If everything works as expected. The next step it to integrate Django Rest Framework and React.

Introduction to React

React is a JavaScript library for building modern user interfaces, developed and used internally by Facebook. It's steadliy growing in popularity among developers worldwide.

React is a declarative and component-based library, it can be rendered in the server side (for boosting load time performance and making your app SEO friendly i.e crawlable by search engines) and can be used to build native mobile applications with React Native

Installing create-react-app

Create React App is a CLI-based utility to generate React apps without the hassle of Webpack and Babel configuration. That doesn't mean these tools are not used but they are just taken care of, so you can focus on building your React app instead of setting up the build environments.

npm install -g create-react-app

What's Webpack?

Webpack is a modern tool for module bundling. It allows web developers to bundle all dependencies (JS scripts, CSS styles and images) into small bundles which reduces the roundtrips to servers (for getting assets).

At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into one or more bundles. -- https://webpack.js.org/concepts/

Pleas note that if you want to customize the Webpack configuration files of your React project you need to eject the configuration of your project using npm run eject.

Tracking the Generated Webpack Bundles

Webpack generates the bundles for your app with hashed filenames so we need a way to track these filenames automatically without having to manually change your template to include the correct filenames, particularly in the development phase where they frequently change.

webpack-bundle-tracker is a Webpack plugin that outputs a JSON file (webpack-stats.json) containing the information we are looking for i.e the names of the bundles.

So head back to your terminal or command line, navigate inside your React project then run the following command to install webpack-bundle-tracker:

npm install webpack-bundle-tracker --save-dev

Next you need to eject the Webpack configuration files so you can include the plugin to your configuration with:

npm run eject

You'll have a config folder with different configuration files for development and production

Creating the Front-end with React

By issuing a few commands you can generate a React app and start building your next app without going through any Webpack configuration.

Next create the React app inside your Django project root folder

npm install -g create-react-app
create-react-app frontend

If the command fails you can try with sudo to execute the install command with the super user priviliges.

You can start the application with:

npm run start

This will start the Webpack development server which serves your app locally with hot loading i.e when you change anything in the source code the server reloads your app automatically.

Open config/webpack.config.dev.js then add:

var BundleTracker  = require('webpack-bundle-tracker');
module.exports = {

    plugins: [
          new BundleTracker({path: "../", filename: 'webpack-stats.json'}),
    ]
}

This will import the bundle tracker plugin and add it to the list of Webpack plugins. We set the path to ../ to point to the root folder of your Django project and the filename to webpack-stats.json.

Next open config/webpack.config.prod.js then add:

var BundleTracker  = require('webpack-bundle-tracker');
module.exports = {

    plugins: [
          new BundleTracker({path: "../", filename: 'webpack-stats.json'}),
    ]
}

This will setup the bundle tracker to generate a file named webpack-stats.json for the bundles information in production.

Create a REST API with Django Rest Framework

Django REST framework is a powerful and flexible toolkit for building Web APIs. Some reasons you might want to use REST framework: The Web browsable API is a huge usability win for your developers. Authentication policies including packages for OAuth1a and OAuth2. Serialization that supports both ORM and non-ORM data sources. Customizable all the way down - just use regular function-based views if you don't need the more powerful features. Extensive documentation, and great community support. Used and trusted by internationally recognised companies including Mozilla, Red Hat, Heroku, and Eventbrite. --http://www.django-rest-framework.org/

Since the communication between React and Django happens over an API we'll need to create a Django API using the Django Rest Framework. But let's start with the development environment

Create a Django Template for Serving the React Front-end

Let's first create the Django template (and its related route and view) where we are going to mount the React app. We need to create a template in templates/main.html after making sure you have configured Django to find your template files.

In project's settings.py, under TEMPLATES array add:

TEMPLATES = [
    {
        # ... 
        'DIRS': [os.path.join(BASE_DIR, "templates"), ],
        # ... 
    },
]

Next let's put some content in the template:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Django + React CRUD</title>
  </head>
  <body>
    <div id="root">
     This is where React will be mounted
    </div>

  </body>
</html>

Once you have done that. Go ahead and create a view and an URL to render the template. Open your project's urls.py file then wire this template to the main URL of your app i.e '^' using the generic TemplateView class:

from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView

urlpatterns = [
    ##
    url(r'^', TemplateView.as_view(template_name="main.html")),
    ##
]

Integrating Django with React

To integrate the Django and the React applications we need to serve the front-end (i.e the React app) using the Django server. The process is simple but we have one problem though! Webpack generates the React bundles dynamically and with hashed filenames so we'll need to use django-webpack-loader--a django application which injects the dynamically generated bundles using the <script> and <link> tags into the Django templates. Using the Webpack loader Django will be able to know which bundle to load in the template.

You'll first need to install the application with pip:

pip install django-webpack-loader

Next you need to add the application (webpack_loader) into INSTALLED_APPS in your project' settings.py file:

Then add the Webpack loader configuration object in settings.py

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

Now you need to change tha main template by adding the following changes:


{ % load render_bundle from webpack_loader % }

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Django + React CRUD</title>
  </head>
  <body>
    <div id="root">
     This is where React will be mounted
    </div>
    { % render_bundle 'main' % }
  </body>
</html>

The render_bundle tag takes 'main' as an argument and renders the script tag for the main bundle.

Open your React src/App.js file then add these changes:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <h1 className="App-title">Welcome to Django</h1>
        </header>
        <p className="App-intro">
            A React app with a Django backend
        </p>
      </div>
    );
  }
}

export default App;

Now you need to start your Webpack server and your Django local development server then navigate to http://localhost:8000/ with your wen browser. You should be able to see the React app running at this address.

Fixing Webpack Hot Reloading

Since we have served the Webpack bundle from the Django server the Webpack dev server will not be able to send XHR requests to React URLs to reload when source files change. So open config/webpackDevServer.config.js then add the following setting:

headers: {
  'Access-Control-Allow-Origin': '*'
},

This tells the Webpack server to accept requests from all origins including http://localhost:8000.

Also make sure to set publicPath and publicUrl to 'http://localhost:3000' in config/webpack.config.dev.js.

That's all you need to do to integrate React and Django for the approach we have followed. In the next tutorial we'll add React routing using react-router-dom then we'll see how to use Redux to manage the app global state. Meanwhile if you have any problems integrating React with Django feel free to post a comment below and I will be glad to help you!

Conclusion

We have seen how to create a React front-end for Django web apps using the Create React App project generator and how to send http requests from React to Django.

REST API Basics with the Django REST Framework

This post is the same as the p...

December 15 2017

December 09 2017

December 08 2017

December 01 2017

November 24 2017

Serializer/Deserializer with utf-8/timezone support

Sorry, this snippet only tested on Django ver.2.0rc1.

November 04 2017

Generic CBV Permissions Helper

A permission helper that can be included in any generic CBV, it uses the model attribute of the class to load all the permissions and tests a user can perform that action before dispatching the view.

October 19 2017

Soft hyphenation filters

Automatically hyphenate raw text or HTML code

October 15 2017

inline forms for deeply nested models

I had a problem trying to display my model would have a foreign key and that model would have one too etc.

Now there was a point I wanted to display the foreign keys of that field and display its fields and so on so forth.

This pretty much expands ...

October 09 2017

add encoding comment to project all python file

add comment "# coding:utf8# to all python file

October 07 2017

Do Not Escape Characters When Using dumpdata Command (Tested in Django 1.11)

Adds --pretty option to django ./manage.py dumpdata command, which produces pretty utf-8 strings instead of ugly unicode-escaped s**t:

$ ./manage.py dumpdata app.pricingplan --indent=1

[
 {
  "pk": 1, 
  "model": "app.pricingplan", 
  "fields": {
   "name": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439", 
  }
 }, 
 {
  "pk": 2, 
  "model": "app.pricingplan", 
  "fields": {
   "name": "\u0425\u0443 ...

October 03 2017

CBV decorator from view function decorator

The Mixin approach for applying permissions to CBV views has 2 issues:

  1. you need to read the code to see what permissions are being applied to a View
  2. multiple bits of disparate code required to specify, e.g., a simple permission check

Here's an alternative -- takes any function decorator ...

September 21 2017

Convert tab indented string to dictionary

output:

{u'Ogrenci': [u'Tum okullar', u'Lisans', u'Onlisans', u'Yuksek Lisans / Doktora', u'Ingilizce Hazirlik'], u'Ogretim Elemani': [u'Tum okullar', u'Lisans', u'Onlisans', u'Yuksek Lisans / Doktora', u'Ingilizce Hazirlik']}

September 17 2017

Automigrate, autocreatesuperuser if not User.count() in runserver and use manage.py:main as entrypoint

With this awesome manage.py, it will try to migrate first when called with runserver.

Also, this manege.py has super power to be used in your entry point as such:

entry_points = {
    'console_scripts': [
        # u haz a setup.py -> u haz importable module :) 
        'yourcommand = yourproject.manage:main',
    ],
},

Example output:

$ yourcommand ...

September 12 2017

Show Logs on Django Admin

Place the code any admin.py file in your registered apps

August 22 2017

Compact primary keys

If the primary key on a table is an integer, it can be desirable after a lot of adding and removing either during testing (as was my case) or otherwise, to tidy up the key space a little and see the primary keys run up as unbroken sequences from 1 ...

August 21 2017

update primary key (cascade to child tables and inherited models) - Django 1.11

An upgrade to the excellent snippet by variant at https://djangosnippets.org/snippets/2915/

Upgraded to work with Django 1.11.

Older posts are this way If this message doesn't go away, click anywhere on the page to continue loading posts.
Could not load more posts
Maybe Soup is currently being updated? I'll try again automatically in a few seconds...
Just a second, loading more posts...
You've reached the end.

Don't be the product, buy the product!

Schweinderl