使用 React 和 Django REST Framework 构建你的网站

在我们最近的工作中,构建网站使用的架构是带有 Django REST Framework(DRF)后端的 React 前端。它们是通过在前端使用 axios(前端库)调用后端 API 来交互的。我们还使用了 Redux(前端库)来存储全局的应用程序状态(存在浏览器端)。这是我们首选,因为它允许前后端完全分离。只要我们提前定义好请求的资源列表(后面单个都简称:endpoint)和返回的数据格式,前端和后端就可以并行的进行开发。这也使我们可以轻松的为未来的任何项目创建移动端 App,因为它们仍然可以复用后端 API。

在本文的剩余部分,我将介绍如何配置 React 前端和 DRF 后端。注意我假设你已经熟悉了 React,Redux,Django,DRF,NPM 等,本篇不是基础教程哦。


后端(The Backend)

除了简单安装 Django 和 DRF 以及设置数据库以外,后端没有太多的工作要做

$ pip3 install django djangorestframework django-filter
$ pip3 freeze > requirements.txt

没错我们用的是 Python3

找一个目录,创建一个 Django 项目和 Django App:

$ django-admin startproject backend
$ cd backend
$ django-admin startapp api

接下来应该配置好你的数据库并编辑你的项目 settings 文件来使用它。在 Django 的官网上可以找到关于如何为你的特定 DB 执行此操作的文档。

或者你也可以什么都不干,它会帮你在项目跟目录创建一个文件数据库:sqlite3.db

最后你还应该按照在这里的说明配置一下 DRF。

有些同学对前后端分离的认证方式有些懵逼,我们下面就看一下前后端分离的架构如何配置认证后端:

# file: api/urls.py
from django.conf.urls import url
from rest_framework.authtoken import views as drf_views

urlpatterns = [
    url(r'^auth$', drf_views.obtain_auth_token, name='auth'),]

只是为了确保清楚,你的 backend/urls.py 文件现在应该是这样:

# file: backend/urls.py
from django.conf.urls import url, include

urlpatterns = [
    url(r'^', include('api.urls', namespace='api', app_name='api')),]

通过这样,我们可以让每个应用程序管理自己的 URL。因为也许将来你会在后端添加更多的应用程序,并且将他们添加到 backend/urls.py。

现在,你已经拥有了一个后端 DRF API:叫 /auth 的 endpoint,访问它可以获得一个身份验证令牌。让我们先配置一个用户,并运行后端服务器以供测试。

$ python3 manage.py migrate
$ python3 manage.py createsuperuser
$ python3 manage.py runserver 0.0.0.0:8000

记得第一次要运行迁移命令(migrate)来创建你的数据库。然后,我们创建一个用户。在服务器运行的情况下,你可以使用 curl 快速测试您的 /auth endpoint:

$ curl -X POST -d "username=username&password=password"
http://localhost:8000/auth

译者在验证过程中发现作者忽略了一些细节,补充如下

1.添加 rest_framework和rest_framework.authtoken 到 INSTALLED_APPS 配置:

# file: backend/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework.authtoken',
]

2.运行命令创建认证 App 所需的数据库:

$ python manage.py migrate

接口 I/O

到这里,后端搞定


前端(The Frontend)

前端我们使用 Facebook 的 create-react-app 脚手架作为 base。首先要做的就是安装它,然后在项目文件夹的根目录下使用它来创建一个新的项目。

$ npm install -g create-react-app
$ create-react-app frontend
$ cd frontend
$ yarn eject

提示:运行 yarn eject 之前必须要提交所有 git 修改,因为它会更改你的文件和添加目录,怕你丢失之前的修改

接下来我们安装一些依赖:

$ npm install --save-dev babel-preset-es2015 babel-preset-stage-3
$ npm install --save redux redux-logger redux-persist react-redux
$ npm install --save axios react-router-dom lodash

现在,我们先只展示将前端连接后端的主要部分。首先创建一个 redux store,用它来保存用户的 token,以便将来进行更多的API调用。

// file: src/store.js
import { compose, createStore, applyMiddleware } from 'redux';
import { createLogger } from 'redux-logger';
import { persistStore, autoRehydrate } from 'redux-persist';
import rootReducer from './reducers';

const store = createStore(
  rootReducer,
  compose(
    applyMiddleware(
      createLogger(),
    ),
    autoRehydrate()
  ));persistStore(store);
export default store;

然后配置 token 的 reducer:

// file: src/reducers/index.js
import { combineReducers } from 'redux';
import * as actionType from '../actions/types';

const tokenInitialState = null;
const token = (state = tokenInitialState, action) => {
  switch(action.type) {
    case actionType.SET_TOKEN:
      return action.data;
    default:
      return state;
  }
}

const appReducer = combineReducers({
  token,
})

const rootReducer = (state, action) => {
  return appReducer(state, action);
}

export default rootReducer;

最后是配置 action(注意代码块有两个不同的文件)

// file: src/actions/index.js
import * as actionType from './types';

export const setToken = (data) => {
  return {
    type: actionType.SET_TOKEN,
    data
  }
}

// file: src/actions/types.js
export const SET_TOKEN = "SET_TOKEN";

有了一个 action,我们现在可以在登录后 dispatch 用户的 token 到 store 中。我们看看如何登录:

// file: src/util/Auth.js
import axios from 'axios';
import _ from 'lodash';
import store from '../store';
import { setToken } from '../actions';
import { URL, LOGIN } from '../config/Api';

export function InvalidCredentialsException(message) {
    this.message = message;
    this.name = 'InvalidCredentialsException';
}

export function login(username, password) {
  return axios.post(URL + LOGIN, {
      username,
      password
    })
    .then(function (response) {
      store.dispatch(setToken(response.data.token));
    })
    .catch(function (error) {
      // raise different exception if due to invalid credentials
      if (_.get(error, 'response.status') === 400) {
        throw new InvalidCredentialsException(error);
      }
      throw error;
    });
}

export function loggedIn() {
  return store.getState().token == null;
}

这段代码使用 axios POST 登录信息到我们的 /auth endpoint,然后将返回的 token

dispatch 到我们的 redux store。一旦完成,我们就可以使用我们存储的 token 令牌来创建一个基于 axios 的 API 客户端(译者注:这样就不需要每次都显式的将令牌信息从 store 中拿出来再插入 payload 中了),这样从我们的 React 组件中的其他地方进行其他 API 调用就很方便了。

// file: src/util/ApiClient.js
import axios from 'axios';
import store from '../store';
import { URL } from '../config/Api';

export const apiClient = function() {
    const token = store.getState().token;
    const params = {
        baseURL: URL,
        headers: {'Authorization': 'Token ' + token}
    };
    return axios.create(params);
}

前面的后两个代码块中我们引用了如下的 ../config/Api 文件。它只是一个将常量映射到 endpoint 的文件,它会使代码更易读,更容易修改。(如果有些懵,可以参考译者按照笔者的思路还原的代码,在文末)

export const URL = process.env.API_URL;
export const LOGIN = "/auth";

这就是一套连接我们的前端和后端的代码了。你现在可以尝试使用 Auth.js 登录功能来获取我们之前创建的用户身份验令牌。这样可以通过从浏览器的开发者工具检查 redux-logger 的输出,来查看 setToken redux 的 action 结果了。

目录总览

如果对一些细节不清楚,或者因为排版问题看不清,可以直接看源代码:

https://github.com/tmpbook/django-with-vuejs/tree/master/examples/django-auth-with-react

原文发布于微信公众号 - 随心DevOps(heart-devops)

原文发表时间:2018-02-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端笔记

【利用无服务器云函数(SCF)】自动刷新COS中变更文件的CDN!

2534
来自专栏老码农专栏

使用 maven 生成一个支持端到端自动测试的 RESTful 服务项目脚手架

1684
来自专栏用户2442861的专栏

Linux网络编程之使用TCP传输文件

原创作品,转载时请务必以超链接形式标明文章原始出处:http://blog.csdn.net/gqb666/article/details/8976263,作...

771
来自专栏极客猴

Django 实战2:利用 Session 实现自动登录机制

上篇文章中讲到 Django 如何启动以及配置 sessions 功能。sessions 功能用是跟踪用户的状态,经常结合 Cookie 功能实现自动登录功能。...

1103
来自专栏运维

ELKB5.2.2集群环境部署及优化终极文档

本人陆陆续续接触了ELK的1.4,2.0,2.4,5.0,5.2版本,可以说前面使用当中一直没有太多感触,最近使用5.2才慢慢有了点感觉,可见认知事务的艰难,本...

572
来自专栏沈唁志

PHP中利用PHPMailer配合QQ邮箱实现发邮件

1292
来自专栏DT乱“码”

ping不可以检查端口是否开放,telnet可以检查端口开放

1590
来自专栏吴生的专栏

使用 maven 生成一个支持端到端自动测试的 RESTful 服务项目脚手架

和传统后端页面生成技术相较, RESTful 数据服务专注与数据逻辑, 而将数据呈现完全交给前端应用. 这样做可以让后端开发更加单纯, 而且更容易测试. 本文将...

3455
来自专栏菩提树下的杨过

log4net快速上手

社区里有一篇 Log4Net使用指南 写得很详细,推荐给准备使用log4net的同学看看。 如果你不想花太多时间研究,也可以按下面的步骤在5分钟内搞定: 1、添...

1889
来自专栏葡萄城控件技术团队

如何在ASP.NET中生成HTML5离线Web应用

传统的Web应用程序有一个很大的症结是当用户的网络连接不好时,应用会加载失败,为了 解决这一问题,HTML5中引入了Web的离线工作的功能。离线功能使得Web应...

1876

扫码关注云+社区