Django and React Integration. Session Auth, CORS | Medium

Шаг 4 — создание модели клиентов и начального набора данных

После создания приложения Django и клиентской части React мы создадим модель клиентов, представляющую таблицу базы данных, где будет храниться информация о клиентах. Вам не потребуется SQL, поскольку Django Object Relational Mapper (ORM) будет обрабатывать операции базы данных посредством сопоставления классов и переменных Python с таблицами и столбцами SQL. Так Django ORM абстрагирует взаимодействия SQL с базой данных через интерфейс Python.

Запустите свою виртуальную среду еще раз:

  1. cd ~
  2. source env/bin/activate

Перейдите в каталог customers и откройте models.py, файл Python, где хранятся модели вашего приложения:

  1. cd ~/djangoreactproject/customers/
  2. nano models.py

Файл будет иметь следующее содержание:

~/djangoreactproject/customers/models.py
from django.db import models
# Create your models here.

API клиентской модели уже импортирован в файл из django.db с помощью выражения import models. Теперь вы добавите класс Customer как расширение models.Model. Каждая модель в Django представляет собой класс Python, являющийся расширением django.db.models.Model.

Customer модель будет иметь следующие поля базы данных:

  • first_name — имя клиента.
  • last_name — фамилия клиента.
  • email — адрес электронной почты клиента.
  • phone — номер телефона клиента.
  • address — адрес клиента.
  • description — описание клиента.
  • createdAt — дата добавления клиента.

Также мы добавим функцию __str__(), определяющую способ отображения модели. В нашем случае это будет имя клиента. Более подробную информацию по построению классов и определению объектов можно найти в документе «Построение классов и определение объектов в Python 3».

Добавьте в файл следующий код:

~/djangoreactproject/customers/models.py
from django.db import models

classCustomer(models.Model):
	first_name = models.CharField("First name", max_length=255)
	last_name = models.CharField("Last name", max_length=255)
	email = models.EmailField()
	phone = models.CharField(max_length=20)
	address =  models.TextField(blank=True, null=True)
	description = models.TextField(blank=True, null=True)
	createdAt = models.DateTimeField("Created At", auto_now_add=True)def__str__(self):return self.first_name

Затем выполните миграцию базы данных для создания таблиц базы данных. Команда makemigrations создает файлы миграции, куда добавляются изменения модели, в команда migrate применяет все изменения в файлах миграции к базе данных.

Перейдите обратно в корневую папку проекта root:

  1. cd ~/djangoreactproject

Запустите следующую команду для создания файлов миграции:

  1. python manage.py makemigrations

Вы получите результат, выглядящий следующим образом:

customers/migrations/0001_initial.py
    - Create model Customer

Примените эти изменения в базе данных:

  1. python manage.py migrate

Вы увидите следующий результат, показывающий, что миграция выполнена успешно:

Введение

Для подключения к Интернету и просмотра сайтов люди используют разные устройства. В связи с этим, приложения должны быть доступными из разных мест. Для традиционных сайтов часто достаточно иметь быстрый пользовательский интерфейс, однако для более сложных приложений обычно требуются другие методики и архитектуры.

Помимо прочего, для создания более сложных веб-приложений можно использовать следующие инструменты:

В этом обучающем руководстве вы создадите современное веб-приложение с отдельными серверным и клиентским REST API, используя React, Django и систему Django REST. Используя React вместе с Django, вы сможете воспользоваться последними достижениями JavaScript и разработки клиентской части.

Вместо создания приложения Django, использующего встроенный механизм шаблонов, вы используете React как библиотеку пользовательского интерфейса. Это позволяет воспользоваться преимуществами виртуальной объектной модели документов (DOM), декларативного подхода и компонентов, быстро обрабатывающих изменения данных.

Создаваемое веб-приложение будет хранить записи о клиентах в базе данных, и вы сможете использовать его как основу для приложения CRM. После завершения обучения вы научитесь создавать, читать, обновлять и удалять записи, используя интерфейс в стиле React с Bootstrap 4.

Adding authentication

In settings.py add this

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES':[
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES':[
'rest_framework.permissions.IsAuthenticated'
]
}

Or you can authentication and permissions per view

from rest_framework.decorators import permission_classes  ,authentication_classes
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
class ListBooksAPI(generics.ListAPIView):
authentication_classes=[ SessionAuthentication ]
permission_classes = [IsAuthenticated]
queryset = Book.objects.all()
serializer_class = BookSerializer

You can add Custom Auth URLs by making APIs for them or add default Django Rest Framework’s auth API URLs in myproject’s urls.py. But these APIs are not Rest-APIs but the basic APIs that you create in normal views. This will provide you a Login/Logout interface using Django Rest Framework Templates.

path('api-auth/', include('rest_framework.urls')),

Now if you go to the URL

Click Log in on the top right section

Fill Details and Submit

And again you can see the same output that you were getting earlier.

Adding cors

CORS means Cross-Origin Resource Sharing. This is done to allow React to be able to get the response from Django Backend which is on a different Origin. Different origin due to port difference. React on 127.0.0.1:3000 and Django on 127.0.0.1:8000. Same IP but different port.

In terminal

pip install django-cors-headers

In settings.py

INSTALLED_APPS = [
...
'corsheaders',
]

Add this in MIDDLEWARE of settings.py

MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
...
]

Also, add this in settings.py

Authentication reducer

Start by creating an auth.js file in frontend/src/reducers/ and add reducer code:

constinitialState={token:localStorage.getItem("token"),isAuthenticated:null,isLoading:true,user:null,errors:{},};exportdefaultfunctionauth(state=initialState,action){switch(action.type){case'USER_LOADING':return{...state,isLoading:true};case'USER_LOADED':return{...state,isAuthenticated:true,isLoading:false,user:action.user};case'LOGIN_SUCCESSFUL':localStorage.setItem("token",action.data.token);return{...state,...action.data,isAuthenticated:true,isLoading:false,errors:null};case'AUTHENTICATION_ERROR':case'LOGIN_FAILED':case'LOGOUT_SUCCESSFUL':localStorage.removeItem("token");return{...state,errors:action.data,token:null,user:null,isAuthenticated:false,isLoading:false};default:returnstate;}}

Basic configurations for creating a rest-api

Install Django Rest Framework in your Django project.

In vscode window of Django project, in its terminal don’t forget to activate the virtualenv

pip install djangorestframework
pip install markdown # Markdown support for the browsable API.
pip install django-filter # Filtering support

In myproject’s settings.py, add required apps

INSTALLED_APPS = [
...
'mainapp',
'rest_framework',
]

Check the expiry and refresh

Let’s decode the token and compare its expiry date with the current time.

Explanation of the effects

Installing this django module will enable you to obtain and refresh access tokens of the JWT style.

Actually making a POST to api/auth/token/obtain/ with a body like this [‘daniel’, ‘1234password’] will return two tokens. The access token usually has a short lifetime.

Full stack django: quick start with jwt auth and react/redux (part i)

This article shows how to quick-start with SPA applications development using Django and React/Redux.

In cmd –

Switch to the directory where you want to start the Django project and create a virtual environment.

virtualenv myprojectenv

Activating virtualenv

.myprojectenvscriptsactivate

Installing Django

pip install django

Creating a Django Project

Logout feature

Now that the application is functional, it is about time we added a basic yet essential feature. To add logout functionality, start by adding a logout action function in frontend/src/actions/auth.js:

Now, let’s use this action in the PonyNote component to show a logout link. Update frontend/src/components/PonyNote.jsx:

import{notes,auth}from"../actions";classPonyNoteextendsComponent{render(){return(<div><h2>WelcometoPonyNote!</h2><hr/><divstyle={{textAlign:"right"}}>{this.props.user.username}(<aonClick={this.props.logout}>logout</a>)</div>{*/KEEPOTHERELEMENTS*/}</div>)}}constmapStateToProps=state=>{return{notes:state.notes,user:state.auth.user,}}constmapDispatchToProps=dispatch=>{return{fetchNotes:()=>{dispatch(notes.fetchNotes());},addNote:(text)=>{returndispatch(notes.addNote(text));},updateNote:(id,text)=>{returndispatch(notes.updateNote(id,text));},deleteNote:(id)=>{dispatch(notes.deleteNote(id));},logout:()=>dispatch(auth.logout()),}}

Making react component and calling rest-api

In terminal

npm install axios

Make a component in ReactJS from where you will trigger the API.

src/ListBookComponent.js

axios.defaults.withCredentials = true; is important to include cookies(here sessionid and csrftoken) in a cross-domain request in axios.

src/App.js

Start the React Server

npm start

Go to URL 127.0.0.1:3000 on the browser and see the result

Please open react on 127.0.0.1:3000 and not localhost:3000 otherwise cookies will not be sent with the cross-domain request because cookies need to be sent to our ListBooks Rest API since we have enabled Session Auth in it.

You must Log in first on 127.0.0.1:8000 before calling this API(as it requires session authentication)

More about cors

CORS_ALLOW_CREDENTIALS is very important in Django settings.py & “withCredentials” in React if you want to send cookies like sessionid and csrftoken with a request (as here we are using session auth) otherwise cookies will not be sent by the browser if a request from a different origin.

Here we are sending cookies stored corresponding to one origin(127.0.0.1:8000) in a browser to that origin’s server from another origin(127.0.0.1:3000)

While Deployment it’s your choice to deploy react on the same origin(same domain) or different. If same-origin then django-cors-headers is not required and nothing to worry about CORS.

Obtain a token

The tokens are stored in the local storage like so:

Open another cmd

Switch to the working directory where you want to create react app and then start the react app.

npx create-react-app myproject-frontend

With session authentication, cors & csrf token mechanism

In this article, I will show you how to integrate React with Django. I will first make a basic REST-API in Django Backend using Django-Rest-Framework and then add session authentication in the backend followed by CORS enabling using django-cors-headers.

Then I will make a component in React project from where I will trigger the API using Axios. I will cover everything about CORS, CSRF Token, SessionId, and other Cookies and Headers. Limitation of session authentication, how cookies are sent over cross-domain, different cases/scenarios in development and deployment mode will also be discussed in this. So this is going to be a one stop solution for Django-React Integration.

Find the code for this project here —

Добавление класса serializer

Создание класса serializer для нашей модели Customer необходимо для преобразования экземпляров клиентов и наборов QuerySets в JSON и обратно. Чтобы создать класс serializer, сначала создайте файл serializers.py в приложении customers:

  1. cd ~/djangoreactproject/customers/
  2. nano serializers.py

Добавьте следующий код для импорта API serializers и модели Customer:

~/djangoreactproject/customers/serializers.py
from rest_framework import serializers
from.models import Customer

Затем создайте класс serializer, являющийся расширением serializers.ModelSerializer и указывающий поля для сериализации:

~/djangoreactproject/customers/serializers.py
...classCustomerSerializer(serializers.ModelSerializer):classMeta:
        model = Customer
        fields =('pk','first_name','last_name','email','phone','address','description')

Класс Meta указывает модель и поля для сериализации: pk, first_name, last_name, email, phone, address, description:

Это полное содержание файла:

~/djangoreactproject/customers/serializers.py
from rest_framework import serializers
from.models import Customer

classCustomerSerializer(serializers.ModelSerializer):classMeta:
        model = Customer
        fields =('pk','first_name','last_name','email','phone','address','description')

Создав класс serializer, мы можем добавить представления API.

Добавление конечных точек api

Теперь мы создадим конечные точки API: api/customers/ для запроса и создания клиентов и api/customers/<pk> для получения, обновления и удаления отдельных клиентов по pk.

Откройте ~/djangoreactproject/djangoreactproject/urls.py:

  1. nano ~/djangoreactproject/djangoreactproject/urls.py

Оставьте его содержание без изменений, но добавьте в начало файла импорт в представление customers:

~/djangoreactproject/djangoreactproject/urls.py

Добавление представлений api

В этом разделе мы создадим представления API для нашего приложения, которое будет вызываться Django, когда пользователь будет посещать конечную точку, соответствующую функции представления.

Откройте ~/djangoreactproject/customers/views.py:

  1. nano ~/djangoreactproject/customers/views.py

Удалите содержимое и добавьте следующие операции импорта:

~/djangoreactproject/customers/views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from.models import Customer
from.serializers import*

Мы импортируем созданный сериализатор, а также модель Customer и API Django и системы Django REST.

Предварительные требования

Для данного курса обучения вам потребуется следующее:

Шаг 1 — создание виртуальной среды python и установка зависимостей

На этом шаге мы создадим виртуальную среду и установим требуемые зависимости для нашего приложения, в том числе Django, систему Django REST и заголовки django-cors-headers.

Шаг 2 — создание проекта django

На этом шаге мы создадим проект Django, используя следующие команды и утилиты:

Шаг 3 — создание клиентской части react

В этом разделе мы создадим клиентское приложение нашего проекта с помощью React.

В React есть официальная утилита, позволяющая быстро генерировать проекты React без прямой настройки Webpack. Webpack — это компоновщик модулей, используемый для компоновки веб-ресурсов, таких как код JavaScript, стили CSS и изображения.

Обычно перед использованием Webpack необходимо настроить различные параметры конфигурации, однако утилита create-react-app позволяет не работать с Webpack напрямую, если вы не захотите внести более детальные настройки. Для запуска create-react-app вы можете использовать инструмент npx, служащий для выполнения двоичных пакетов npm.

Переключитесь на второй терминал и убедитесь, что вы находитесь в каталоге проекта:

  1. cd ~/djangoreactproject

Создайте проект React под названием frontend с помощью create-react-app и npx:

  1. npx create-react-app frontend

Воспользуйтесь навигацией по вашему приложению React и запустите сервер разработки:

  1. cd ~/djangoreactproject/frontend
  2. npm start

Шаг 5 — создание api rest

На этом шаге мы создадим API REST с помощью системы Django REST. Мы создадим несколько разных представлений API. Представление API представляет собой функцию, выполняющую запрос или вызов API, а конечная точка API — уникальный URL, представляющий собой элемент связи с системой REST.

Также мы используем сериализаторы. Сериализатор в системе Django REST позволяет преобразовывать экземпляры сложных моделей и наборы QuerySets в формат JSON для использования API. Класс serializer может работать и в другом направлении, предоставляя механизмы для синтаксического анализа и десериализации данных в моделях Django и QuerySets.

Мы получим следующие конечные точки API:

  • api/customers: эта конечная точка используется для создания клиентов и возврата разбитых на страницы наборов клиентов.
  • api/customers/: эта конечная точка испольузется для получения, обновления и удаления отдельных клиентов по первичным ключам или идентификаторам.

Мы также создадим URL в файле проекта urls.py для соответствующих конечных точек (т.е. api/customers и api/customers/).

Начнем с создания класса serializer для нашей модели Customer.

Шаг 7 — отображение данных из api в приложении react

На этом шаге мы создадим компонентCustomersList React. Компонент React представляет часть пользовательского интерфейса; также он позволяет разделять пользовательский интерфейс на независимые элементы многоразового использования.

Для начала создайте CustomersList.js в папке frontend/src:

  1. nano ~/djangoreactproject/frontend/src/CustomersList.js

Вначале импортируйте React и Component для создания компонента React:

~/djangoreactproject/frontend/src/CustomersList.js
import  React,{ Component }from'react';

Затем импортируйте и создайте экземпляр модуля CustomersService, который вы создали на предыдущем шаге и который предоставляет методы взаимодействия с серверной частью REST API:

~/djangoreactproject/frontend/src/CustomersList.js
...import  CustomersService  from'./CustomersService';const  customersService  =newCustomersService();

Затем создайте компонент CustomersList, расширяющий Component для вызова REST API. Компонент React должен расширять класс Component или создавать его подкласс. Дополнительную информацию о классах E6 и наследовании можно найти в обучающем руководстве «Понимание классов в JavaScript».

Шаг 8 — добавление компонентов react для создания и обновления клиентов

На этом шаге мы создадим компонент CustomerCreateUpdate, который будет заниматься созданием и обновлением клиентов. Для этого он будет предоставлять форму, где пользователи смогут вводить данные о новом клиенте или изменять уже записанные данные.

Создайте в папке frontend/src файл CustomerCreateUpdate.js:

  1. nano ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

Добавьте следующий код для создания компонента React, импортировав классы React и Component:

~/djangoreactproject/frontend/src/CustomerCreateUpdate.js
import  React,{ Component }from'react';

Также мы можем импортировать класс CustomersService, созданный на предыдущем шаге и создать экземпляр этого класса, который предоставляет методы взаимодействия с серверной частью API REST:

~/djangoreactproject/frontend/src/CustomerCreateUpdate.js
...import  CustomersService  from'./CustomersService';const  customersService  =newCustomersService();

Далее создайте компонент CustomerCreateUpdate, расширяющий класс Component для создания и обновления клиентов:

~/djangoreactproject/frontend/src/CustomerCreateUpdate.js
...classCustomerCreateUpdateextendsComponent{constructor(props){super(props);}}exportdefault CustomerCreateUpdate;

Добавьте в определение класса метод компонента render(), отвечающий за рендеринг формы HTML, куда вводится информация о клиенте:

~/djangoreactproject/frontend/src/CustomerCreateUpdate.js
...render(){return(<form onSubmit={this.handleSubmit}><div className="form-group"><label>
              First Name:</label><input className="form-control" type="text" ref='firstName'/><label>
              Last Name:</label><input className="form-control" type="text" ref='lastName'/><label>Phone:</label><input className="form-control" type="text" ref='phone'/><label>Email:</label><input className="form-control" type="text" ref='email'/><label>Address:</label><input className="form-control" type="text" ref='address'/><label>Description:</label><textarea className="form-control" ref='description'></textarea><input className="btn btn-primary" type="submit" value="Submit"/></div></form>);}

Для каждого элемента ввода формы метод добавляет свойство ref для доступа и установки значения элемента формы.

Над методом render() создайте определение метода handleSubmit(event), чтобы при нажатии на кнопку Submit (Отправить) функция работала надлежащим образом:

~/djangoreactproject/frontend/src/CustomerCreateUpdate.js
...handleSubmit(event){const{match:{ params }}=this.props;if(params  &&  params.pk){this.handleUpdate(params.pk);}else{this.handleCreate();}
	event.preventDefault();}...

Метод handleSubmit(event) обрабатывает отправку форм и (в зависимости от маршрута) вызывет метод handleUpdate(pk) для обновления клиента с переданным pk или метод handleCreate() для создания нового клиента. Мы дадим краткое определение этих методов.

Выполните в конструкторе компонентов привязку добавленного метода handleSubmit() к этому методу, чтобы вы могли использовать его в своей форме:

~/djangoreactproject/frontend/src/CustomerCreateUpdate.js
...classCustomerCreateUpdateextendsComponent{constructor(props){super(props);this.handleSubmit =this.handleSubmit.bind(this);}...

Затем дайте определение методу handleCreate() для создания клиента на основе данных формы. Над методом handleSubmit(event) добавьте следующий код:

~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

Шаг 9 — обновление компонента main app

На этом шаге мы обновим компонент App нашего приложения для создания ссылок на компоненты, созданные на предыдущих шагах.

Запустите из папки frontend следующую команду для установки React Router, что позволит добавить маршрутизацию и навигацию между разными компонентами React:

  1. cd ~/djangoreactproject/frontend
  2. npminstall --save react-router-dom

Далее откройте ~/djangoreactproject/frontend/src/App.js:

  1. nano ~/djangoreactproject/frontend/src/App.js

Удалите все содержимое и добавьте следующий код, чтобы импортировать необходимые классы для добавления маршрутизации. В их число входит `класс BrowserRouter, создающий компонент Router, и класс Route, создающий компонент route:“`

~/djangoreactproject/frontend/src/App.js
import  React,{ Component }from'react';import{ BrowserRouter }from'react-router-dom'import{ Route, Link }from'react-router-dom'import  CustomersList  from'./CustomersList'import  CustomerCreateUpdate  from'./CustomerCreateUpdate'import'./App.css';

BrowserRouter обеспечивает синхронизацию пользовательского интерфейса с URL, используя API истории HTML5.

Далее создайте базовую схему, обеспечивающую базовый компонент для включения в компонент BrowserRouter:

~/djangoreactproject/frontend/src/App.js

The frontend

In the first step I implemented this with Vue.JS but currently I was trying to get something done with React so here are the important steps to:

  1. Obtain a token
  2. Check the expiry and refresh
  3. Make an authorized fetch
  4. “Logging out”

Again the “heavy” lifting will be done by a dedicated module: npm install –save jwt-decode

All of the following code happens in a global service called JWTService.

Заключение

Это обучающее руководство помогло вам научиться создавать демонстрационное приложение с помощью Django и React. Вы использовали систему Django REST для создания REST API, Axios для потребления API, и Bootstrap 4 для стилизации CSS. Исходный код этого проекта можно найти в хранилище GitHub.

В этом обучающем руководстве были использованы отдельные приложения для клиентской части и серверной части. Другой подход к интеграции React с Django можно найти в этом руководстве и этом руководстве.

Дополнительную информацию о создании приложений с помощью Django можно найти в серии публикаций «Разработка в Django». Также вы можете ознакомиться с официальной документацией по Django.

Example of a react spa that logs into a django backend with jwt

A scenario for SPAs is that you might be building it to further use it in a mobile app (maybe react-native).
To avoid switching from session_ids stored in secure cookies which is the standard way of django doing it you could use a JWT.

Adding set csrf token rest-api in backend

If csrftoken not set on 127.0.0.1:8000, then to handle this case on React (if you use Django directly then it automatically sets CSRF token) you will have to make a new REST-API and call that once in starting and then call other APIs requiring that.

from django.utils.decorators import method_decorator
from rest_framework.response import Response
from django.views.decorators.csrf import ensure_csrf_cookie
ensure_csrf = method_decorator(ensure_csrf_cookie)
class setCSRFCookie(APIView):
permission_classes = []
authentication_classes = []
@ensure_csrf
def get(self, request):
return Response("CSRF Cookie set.")

Calling setCSRFCookie API from React —

Похожее:  Интернет-банкинг для юридических лиц, АО «Банк ЦентрКредит»

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *