フロントエンド環境を構築
開発用サイトを Django 側に登録します。
ここでの開発用サイトは localhost:3000 を指します。ユーザ登録時、ユーザに送信されるメール本文の中に使用されますので、フロントエンド環境を設定する前に済ませておきます。ちなみに、( 本番環境なら your-domain.com のように変更する必要があります )
project/settings.py の EMAIL_FILE_PATH と DEFAULT_FROM_EMAIL の内容がメール本文に反映されます。
EMAIL_FILE_PATH = ‘tmp/emails’
DEFAULT_FROM_EMAIL = ‘admin@mydomin.com’
※ メールログの例:
Content-Type: text/plain; charset=”utf-8″
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Please Confirm Your E-mail Address
From: admin@mydomin.com << project/settings.py の DEFAULT_FROM_EMAIL
To: user@your-domain.com << 登録メールアドレス
Date: Tue, 08 Oct 2019 23:07:55 -0000
Message-ID: <157057607508.47435.10310212505214298311@macadmin>
Hello from example.com! << project/settings.py の SITE_ID のドメイン
You’re receiving this e-mail because user testuser has given yours as an e-mail address to connect their account.
To confirm this is correct, go to example.com/account/confirm-email/MQ:1iHyaB:fqDiwW_LQoeVDGjXWRYyM4nFvPE/
Thank you from example.com!
example.com
- 1Django Admin サイトにログインします。
http://localhost:8000/admin/sites/site/add
- 2localhost:3000 を登録します。

※ デフォルトで example.com ドメインが入っていますが、削除しないでください。
- 3追加されたサイト名をクリックします。

若しくは、サイト名にマウスオーバーしてブラウザ左下のステータスメッセージでサイトIDが確認できます。確認できたらサイト名をクリックしなくて結構です。
http://127.0.0.1/admin/sites/site/2/change/ - 4URL 入力欄からサイト ID を確認します。
ここではサイト ID = 2です。( サイト ID は環境によって異なります )

- 5サイト ID を Django 環境に反映します。
project/settings.py を開き、SITE_ID = 1 を 上記で確認したサイト ID に変更します。ここでは最終的には SITE_ID = 2 になります。
Create-react-app ツールを使用して React アプリを作成します。
try🐶everything email-auth$ npx create-react-app frontend ... try🐶everything email-auth$ cd frontend/ try🐶everything frontend$ yarn start
http://localhost:3000 にアクセス出来るか確認します。問題なければ Ctrl+C で React 開発サーバを閉じておきます。
フロントエンド用ソースをコピペします。
※ reactjs-auth-django-rest を利用しますが、そのままではエラーが発生するため使えません。したがって、以下の手順で修正していきます。
- 1reactjs-auth-django-rest からフロントエンドソースをコピペします。
try🐶everything email-auth$ git clone https://github.com/ZachLiuGIS/reactjs-auth-django-rest try🐶everything email-auth$ cp -r reactjs-auth-django-rest/react_frontend/src/* frontend/src/
- 2必要なパッケージをインストールします。
try🐶everything src$ npm i prop-types react-router-dom react-redux bootstrap redux redux-form redux-form-validators redux-logger redux-notifications redux-thunk react-redux history axios
- 3const 文の位置を調整します。
yarn start コマンドで React 開発サーバを起動すると、下記のようなエラーが発生します。
エラー:
Failed to compile.
./src/actions/authActions.js
Line 8:1: Import in body of module; reorder to top import/first
Line 9:1: Import in body of module; reorder to top import/first
Line 10:1: Import in body of module; reorder to top import/first
Line 11:1: Import in body of module; reorder to top import/first
Search for the keywords to learn more about each error.対処:
actions/authActions.js ファイルを開き、const { notifSend } = notifActions; 文を import 文の下に移動しておきます。vi actions/authActions.js
import axios from “axios”;
import { SubmissionError } from ‘redux-form’;
import history from “../utils/historyUtils”;
import { actions as notifActions } from ‘redux-notifications’;
import { AuthTypes } from “../constants/actionTypes”;
import { AuthUrls } from “../constants/urls”;
import store from “../store”;
import { getUserToken } from “../utils/authUtils”;
const { notifSend } = notifActions; << ここに移動! - 4switch 文を修正します。
reducers/authReducer.js ファイルを開き、
default:を追記します。vi reducers/authReducer.js
import { AuthTypes } from “../constants/actionTypes”;
export default function(state = {}, action) {
switch(action.type) {
case AuthTypes.LOGIN:
return { …state, authenticated: true, token: action.payload};
case AuthTypes.LOGOUT:
return { …state, authenticated: false, token: null};
case AuthTypes.USER_PROFILE:
return { …state, user: action.payload};
default: << 追加!
}
return state;
} - 5history の書き方を修正します。
utils/historyUtils.js ファイルを下記のように修正します。
vi utils/historyUtils.js
// import createHistory from “history/createBrowserHistory”;
// export default createHistory();
↓↓↓
import { createBrowserHistory } from ‘history’
export default createBrowserHistory(); - 6Notifs 設定を修正します。
エラー:
Could not find “store” in either the context or props of “Connect(Notifs)”. Either wrap the root component in a , or explicitly pass “store” as a prop to “Connect(Notifs)”.対処:
components/auth/App.js ファイルを修正します。vi components/auth/App.js
import React, { Component } from “react”;
import { Notifs } from “redux-notifications”;
import store from “../store”; << 追加!
import Header from “./Header”;
import MainContent from “./MainContent”;
export default class App extends Component {
render() {
return (
<div className=”container”>
<Notifs store={store} /> << 修正!
<Header />
<MainContent />
</div>
)
}
}これで、問題なく起動できると思います!
- 7no-unused-vars
エラー:
./src/components/auth/UserProfileEdit.js
Line 4:10: ‘required’ is defined but never used no-unused-vars対処:
該当行をコメントアウトするか削除します。import React, { Component } from "react"; import { reduxForm, Field, propTypes } from "redux-form"; import { connect } from "react-redux"; // import { required } from "redux-form-validators"
ユーザを登録
http://localhost:3000/signup から登録できます。


すると、アカウントを有効化するためのメールが送信されます。
有効な SMTP 設定をすれば、登録メールに送られますが、ここでは開発用の設定をしているためtmp/emails/ の下にメールログだけが保存されます。( ▼ )

メール本文のリンク ( ↑赤い線 ) をコピーしてブラウザの URL 入力欄にペーストします。

これで、メール認証でユーザ登録ができました。
以下は、ユーザ認証には直接関係ありませんが、登録ユーザのプロフィールをアップデートするための設定です。
UserProfile 項目を修正します。( 任意 )
components/auth/UserProfile.js を修正します。( Line 27〜29 )
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { getUserProfile } from "../../actions/authActions";
class UserProfile extends Component {
static propTypes = {
getUserProfile: PropTypes.func.isRequired,
user: PropTypes.object
};
componentWillMount() {
this.props.getUserProfile();
}
renderUser() {
const user = this.props.user;
console.log(user);
if (user) {
return (
<div className="mx-2">
<h4>Username: {user.username}</h4>
<h4>First Name: {user.first_name}</h4>
<h4>Last Name: {user.last_name}</h4>
<h4>E-mail: {user.email}</h4>
<h4>Company: {user.company}</h4>
<h4>Department: {user.department}</h4>
<h4>Current Position: {user.current_position}</h4>
<hr />
<h4>About Myself:</h4>
<p>{user.about}</p>
</div>
);
}
return null;
}
render() {
return (
<div>
{this.renderUser()} <hr />
<Link className="btn btn-primary mr-2" to="/profile_edit">
Update Profile
</Link>
<Link className="btn btn-primary" to="/change_password">
Change Password
</Link>
</div>
);
}
}
function mapStateToProps(state) {
return {
user: state.auth.user
};
}
export default connect(
mapStateToProps,
{ getUserProfile }
)(UserProfile);
components/auth/UserProfileEdit.js を修正します。 ( Line 56〜81 )
import React, { Component } from "react";
import { reduxForm, Field, propTypes } from "redux-form";
import { connect } from "react-redux";
import {
renderField,
renderTextAreaField,
renderError
} from "../../utils/renderUtils";
import { updateUserProfile } from "../../actions/authActions";
class Login extends Component {
static propTypes = {
...propTypes
};
render() {
const { handleSubmit, error } = this.props;
return (
<div className="row justify-content-center">
<form
className="col col-sm-4 card mt-5 p-2"
onSubmit={handleSubmit}
>
<h4 className="text-md-center">Edit Profile</h4>
<hr />
<fieldset className="form-group">
<Field
name="username"
label="Username"
component={renderField}
type="text"
/>
</fieldset>
<fieldset className="form-group">
<Field
name="first_name"
label="First Name"
component={renderField}
type="text"
/>
</fieldset>
<fieldset className="form-group">
<Field
name="last_name"
label="Last Name"
component={renderField}
type="text"
/>
</fieldset>
<fieldset className="form-group">
<Field
name="company"
label="Company"
component={renderField}
type="text"
/>
</fieldset>
<fieldset className="form-group">
<Field
name="department"
label="Department"
component={renderField}
type="text"
/>
</fieldset>
<fieldset className="form-group">
<Field
name="current_position"
label="Current Position"
component={renderField}
type="text"
/>
</fieldset>
<fieldset className="form-group">
<Field
name="about"
label="About Yourself"
component={renderTextAreaField}
type="text"
/>
</fieldset>
<fieldset className="form-group">
{renderError(error)}
<button action="submit" className="btn btn-primary">
Save
</button>
</fieldset>
</form>
</div>
);
}
}
function mapStateToProps(state) {
return {
initialValues: state.auth.user
};
}
export default connect(mapStateToProps)(
reduxForm({
form: "update_user_profile",
onSubmit: updateUserProfile
})(Login)
);
UserProfile をアップデートしてみます。
下記のリンクへアクセスし、変更した項目でアップデートできるか確認します。
http://localhost:3000/profile
http://localhost:3000/profile_edit
また、http://localhost:8000/api/user と http://localhost:8000/admin でも確認できます。
問題なく修正できれば OK です。
あとがき
※ やり残したこと ( メモ ):
・機能追加:ソーシャルログイン ( facebook / twitterなど )
※ 2019/12/18追記:興味のある方はご参考にどうぞ!▼
Twitter ソーシャルログイン機能を実装する〜Reactjs + Django〜
・登録時、Confirm Email フィールドを追加
・パスワードをリセットする際、登録されたメールアドレスかをチェック


コメント