In diesem Artikel lernen wir den Prozess der Kommunikation zwischen dem Django-Backend und dem React js-Frontend mithilfe des Django-REST-Frameworks kennen. Zum besseren Verständnis des Konzepts werden wir einen Simple Task Manager erstellen und die primären Konzepte für diese Art der Integration zwischen React js und Django durchgehen.

Integrating-Django-with-Reactjs-using-Django-REST-Framework

Reactjs ist kurz gesagt eine Javascript-Bibliothek zur Entwicklung von Single Page Applications (SPA) mit sehr detaillierter und gut strukturierter Dokumentation . Für dieses Projekt wird React als Frontend dienen und die Benutzeroberfläche (UI) über die Requests an das Backend von Django handhaben.

Projektübersicht:

Schauen wir uns zuerst an, was wir bauen werden. Die folgenden Bilder zeigen die Benutzeroberfläche des Task-Managers.

Diese Task-Manager-Anwendung ist eine Art Aufgabenliste. Hier haben wir drei Schaltflächen wie „Abgeschlossen“, „Unvollständig“ und eine Schaltfläche zum Hinzufügen der Aufgabe mit dem Namen „Aufgabe hinzufügen“, wie im obigen Bild gezeigt.

Um eine Aufgabe hinzuzufügen, klicken Sie auf die Schaltfläche Aufgabe hinzufügen, wodurch ein Fenster in der App geöffnet wird, um die Aufgabe wie unten gezeigt hinzuzufügen. Hier können wir den „Titel“ für die Aufgabe hinzufügen und ihr im Abschnitt „Beschreibung“ eine Beschreibung geben. Schließlich können Sie je nach Status der Aufgabe (z. B. Abgeschlossen oder Unvollständig) ein Häkchen setzen oder das Häkchen entfernen, wie im folgenden Bild gezeigt:

Nachdem Sie die Aufgabe „gespeichert“ haben, können Sie zwischen den Registerkarten „Erledigt“ und „Unvollständig“ navigieren, um die Aufgaben wie unten gezeigt zu verfolgen:

Hier haben Sie auch die Möglichkeit, eine bestehende Aufgabe zu „löschen“ oder zu „bearbeiten“, wie unten gezeigt:

Alle oben ausgeführten Operationen werden vom Django REST Framework verwaltet.

Projektaufbau:

Voraussetzungen:

Die Voraussetzungen für das Projekt sind also:

Um zu überprüfen, ob Sie Python 3 installiert haben, verwenden Sie den folgenden Befehl in Ihrer Eingabeaufforderung (Da dieses Projekt auf einem Windows-Computer entwickelt wird, verwenden wir die Eingabeaufforderung, aber abhängig von Ihrem Betriebssystem können Sie das Terminal verwenden):

python -V

Dadurch wird die aktuelle Python-Version auf Ihrem System angezeigt, wie unten gezeigt:

Verwenden Sie den folgenden Befehl, um zu überprüfen, ob das Node-Modul installiert ist:

node --version

Dies zeigt Ihnen die Nodeversion auf Ihrem System wie unten gezeigt:

An diesem Punkt können wir loslegen, da wir Python und Node js in unserem System installiert haben.

Implementierung:

Beginnen wir mit dem Backend.

Backend (Django):

Öffnen wir nun unsere Eingabeaufforderung. Befolgen Sie nun die folgenden Schritte in der gleichen Reihenfolge, um diesem Artikel zu folgen.

Schritt 1: Erstellen Sie ein Verzeichnis namens „django-react-app“ mit dem folgenden Befehl (der Befehl kann sich je nach Betriebssystem leicht ändern):

mkdir django-react-app

Schritt 2: Mit dem folgenden Befehl in das Verzeichnis verschoben, das wir gerade erstellt haben:

cd django-react-project

Schritt 3: Erstellen Sie nun eine virtuelle Umgebung mit dem folgenden Befehl:

python -m venv dar

Wir haben unsere virtuelle Umgebung „dar“ genannt , kurz für Django und React. Dies ist notwendig, da wir Pakete und Abhängigkeiten nicht global installieren müssen. Es ist auch eine gute Programmierpraxis.

Schritt 4: Aktivieren Sie die virtuelle Umgebung, die wir gerade erstellt haben, mit dem folgenden Befehl:

dar\Scripts\activate.bat

Dadurch wird unsere virtuelle Maschine wie unten gezeigt aktiviert:

Schritt 5: Installieren Sie nun Django in der virtuellen Maschine mit dem folgenden Befehl:

pip install django

Sie erhalten eine ähnliche Meldung, wenn Ihre Installation abgeschlossen ist:

Schritt 6: Lassen Sie uns nun unser Projekt namens „ backend“ für unser Django-Backend erstellen. Verwenden Sie dazu den folgenden Befehl:

django-admin startproject backend

Die django-react-app wird unser Hauptordner sein und darin werden wir zwei Ordner haben, einen für das Backend und einen für das Frontend, die wir später erstellen werden.

Schritt 7: Navigieren Sie nun mit dem folgenden Befehl zum Backend-Ordner:

cd backend

Schritt 8: Jetzt starten wir unsere App und nennen sie „todo“ mit dem folgenden Befehl:

python manage.py startapp todo

Die App wird mit dem obigen Befehl wie unten gezeigt erstellt:

Lassen Sie uns jetzt fortfahren und den VS-Code starten und den darin enthaltenen Projektordner öffnen. In dieser Phase sieht unsere Projektstruktur wie folgt aus:

 Schritt 9: Verwenden Sie nun den folgenden Befehl, um das Projekt zu migrieren:

python manage.py migrate

Die Migrationen werden wie unten gezeigt angewendet:

Schritt 10: Lassen Sie uns nun den Server mit dem folgenden Befehl ausführen:

python manage.py runserver

Jetzt können Sie den localhost besuchen , um zu überprüfen, ob das Projekt ordnungsgemäß gestartet wurde. Wie Sie im folgenden Bild sehen können, ist das Projekt in Betrieb:

Schritt 11: Jetzt müssen wir einige Konfigurationsschritte in der Datei settings.py durchführen. Fügen Sie im Abschnitt INSTALLED_APPS den Namen der App hinzu, die wir erstellt haben (z. B. todo), wie unten gezeigt:

Python3

# Application definition
  
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todo',
]

Zu diesem Zeitpunkt würde die Datei settings.py wie folgt aussehen:

Python3

from pathlib import Path
  
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
  
  
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
  
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-_c3!4)8+yce2l-ju@gz@b6(e0$00y@xhx7+lxk1p==k+pyqko3'
  
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
  
ALLOWED_HOSTS = []
  
  
# Application definition
  
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todo',
]
  
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
]
  
ROOT_URLCONF = 'backend.urls'
  
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]
  
WSGI_APPLICATION = 'backend.wsgi.application'
  
  
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
  
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
  
  
# Password validation
# https://docs.djangoproject.com/en/3.2/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',
    },
]
  
  
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
  
LANGUAGE_CODE = 'en-us'
  
TIME_ZONE = 'UTC'
  
USE_I18N = True
  
USE_L10N = True
  
USE_TZ = True
  
  
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
  
STATIC_URL = '/static/'
  
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
  
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Schritt 12: Als nächstes müssen wir ein Modell erstellen. Das Modell bestimmt, wie die ToDo - Elemente in der Datenbank gespeichert werden. Wir haben drei Eigenschaften im Modell:

  • Titel: Dies ist der Titel der Aufgabe mit einer maximalen Länge von 150 Zeichen.
  • Beschreibung: Dies ist die Beschreibung der Aufgabe mit einer maximalen Länge von 500 Zeichen.
  • Abgeschlossen: Dies ist ein boolescher Wert, der verwendet wird, um den aktuellen Status der Aufgabe zu bestimmen. Standardmäßig wird es auf false gesetzt.

Öffnen Sie also die Datei "models.py " und den folgenden Code:

Python3

class Todo(models.Model):
    title=models.CharField(max_length=150)
    description=models.CharField(max_length=500)
    completed=models.BooleanField(default=False)

Wir werden auch eine Zeichenfolgendarstellung des Titels in der Todo-Klasse wie folgt erstellen:

Python3

def __str__(self):
  
  #it will return the title
  return self.title G")

Zu diesem Zeitpunkt sieht unsere Datei " models.py " folgendermaßen aus:

Python3

from django.db import models
  
class Todo(models.Model):
    title=models.CharField(max_length=150)
    description=models.CharField(max_length=500)
    completed=models.BooleanField(default=False)
  
    # string representation of the class
    def __str__(self):
  
        #it will return the title
        return self.title 

Schritt 13: Lassen Sie uns nun fortfahren und Migrationen durchführen. Beachten Sie, dass wir jedes Mal, wenn Sie Änderungen an der Datei "models.py " vornehmen, Migrationen vornehmen müssen. Verwenden Sie dazu den folgenden Befehl:

python manage.py makemigrations

Die folgende Nachricht wird generiert, wenn Ihre Migration fertig ist:

Schritt 14: Wenden wir nun alle Migrationen mit dem folgenden Befehl an:

python manage.py migrate

Dies wendet unsere Migrationen wie unten gezeigt an:

Jetzt können wir testen, ob die CRUD-Operationen mit der Todo-Modelldatei funktionieren, indem wir die Admin-Site (oder die Schnittstelle) verwenden. Dazu müssen wir die Modelle in der Datei admin.py registrieren .

Schritt 15: Öffnen Sie die Datei admin.py und fügen Sie den folgenden Code darin ein:

Python3

from django.contrib import admin
  
# import the model Todo
from .models import Todo
  
# create a class for the admin-model integration
class TodoAdmin(admin.ModelAdmin):
  
    # add the fields of the model here
    list_display = ("title","description","completed")
  
# we will need to register the
# model class and the Admin model class
# using the register() method
# of admin.site class
admin.site.register(Todo,TodoAdmin)

Schritt 16: Jetzt erstellen wir einen Superuser mit dem folgenden Befehl:

python manage.py createsuperuser

Hier verwenden wir die folgenden Anmeldeinformationen:

  • Benutzername: Geeks
  • E-Mail-Adresse: geeks@geeksforgeeks.org
  • Passwort: 12345

Hinweis: Sie können Ihre Anmeldeinformationen nach Bedarf einrichten. Die oben genannten Anmeldeinformationen müssen nicht identisch sein. 

Wir würden die folgende Nachricht erhalten, wenn der Superuser erstellt wird:

Schritt 17: Lassen Sie uns nun den Server ausführen und überprüfen, ob alles wie vorgesehen läuft, indem Sie den folgenden Befehl verwenden:

python manage.p runserver

Navigieren Sie zu folgendem Link:

http://127.0.0.1:8000/admin/login/?next=/admin/

Dies zeigt uns die Admin-Seite wie unten gezeigt:

Geben Sie hier Ihre Anmeldeinformationen ein und melden Sie sich an. Wir verwenden die Anmeldeinformationen, die wir beim Erstellen des Superusers verwendet haben:

Dies führt uns auf die folgende Seite. Hier sehen wir unsere Benutzer, die App und die Gruppen wie unten gezeigt:

Benutzer:

Machen:

Lassen Sie uns eine Aufgabe hinzufügen und wie unten gezeigt speichern:

Wir können diese Aufgabe wie unten gezeigt im ToDo-Abschnitt sehen:

Erstellen der API:

Um die API zu erstellen, müssen wir das Django REST Framework für Serializer installieren. Wir müssen auch django-cors-headers für das Whitelisting von Port 3000 verwenden, der der Standardport für React ist.

Befolgen Sie nun die folgenden Schritte, um das Django-REST-Framework zu erstellen:

Schritt 1:   Um das Django-REST-Framework zu installieren, verwenden Sie den folgenden Befehl im Backend-Verzeichnis:

pip install djangorestframework

Die folgende Meldung wird angezeigt, sobald die Installation abgeschlossen ist:

Schritt 2: Installieren Sie nun die django-cors-headers mit dem folgenden Befehl:

pip install django-cors-headers

Die folgende Meldung wird angezeigt, sobald die Installation abgeschlossen ist:

Schritt 3: Öffnen Sie nun die Datei setting.py und fügen Sie beide Abhängigkeiten, die wir gerade installiert haben, wie unten gezeigt zu INSTALLED_APPS hinzu:

Python3

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

Schritt 4: Auch in der Datei settings.py müssen wir den localhost-Port 3000 auf die Whitelist setzen. Wenn wir das nicht tun, wird es einen Block zwischen localhost:8000 und localhost:3000 geben. Fügen Sie den folgenden Code hinzu, um dasselbe zu erreichen:

Python3

# White listing the localhost:3000 port
# for React
CORS_ORIGIN_WHITELIST = (
    'http://localhost:3000'
)

Schritt 5: Im Abschnitt MIDDLEWARE müssen wir die cors-headers-Einstellungen wie unten gezeigt hinzufügen:

Python3

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
    'corsheaders.middleware.CorsMiddleware'
]

Zu diesem Zeitpunkt würde unsere settings.py wie folgt aussehen:

Python3

from pathlib import Path
  
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
  
  
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
  
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-_c3!4)8+yce2l-ju@gz@b6(e0$00y@xhx7+lxk1p==k+pyqko3'
  
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
  
ALLOWED_HOSTS = []
  
  
# Application definition
  
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todo',
    'corsheaders',
    'rest_framework',
]
  
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
    'corsheaders.middleware.CorsMiddleware'
]
  
ROOT_URLCONF = 'backend.urls'
  
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]
  
WSGI_APPLICATION = 'backend.wsgi.application'
  
  
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
  
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
  
  
# Password validation
# https://docs.djangoproject.com/en/3.2/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',
    },
]
  
# White listing the localhost:3000 port
CORS_ORIGIN_WHITELIST = (
    'http://localhost:3000'
)
  
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
  
LANGUAGE_CODE = 'en-us'
  
TIME_ZONE = 'UTC'
  
USE_I18N = True
  
USE_L10N = True
  
USE_TZ = True
  
  
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
  
STATIC_URL = '/static/'
  
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
  
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Jetzt müssen wir die Sereilizer für das Todo-Datenmodell erstellen. Die Serilaizer sind dafür verantwortlich, dass Serializer Modellinstanzen für JSON erstellen. Dies hilft dem Frontend, mit den empfangenen Daten einfach zu arbeiten. JSON ist der Standard für den Datenaustausch im Web.

Schritt 6: Erstellen Sie nun eine Datei im todo-Ordner und nennen Sie sie serializers.py. Fügen Sie im Ordner den folgenden Code hinzu:

Python3

# import sereliazers from the REST framework
from rest_framework import serializers
  
# import the todo data model
from .models import Todo
  
# create a sereliazer class
class TodoSerializer(serializers.ModelSerializer):
  
    # create a meta class
    class Meta:
        model = Todo
        fields = ('id', 'title','description','completed')

Schritt 7: Jetzt ist es an der Zeit, die Ansichten zu erstellen. Öffnen Sie also die Datei views.py . Fügen Sie nun den folgenden Code in die Datei ein:

Python3

from django.shortcuts import render
  
# import view sets from the REST framework
from rest_framework import viewsets
  
# import the TodoSerializer from the serializer file
from .serializers import TodoSerializer
  
# import the Todo model from the models file
from .models import Todo
  
# create a class for the Todo model viewsets
class TodoView(viewsets.ModelViewSet):
  
    # create a sereializer class and 
    # assign it to the TodoSerializer class
    serializer_class = TodoSerializer
  
    # define a variable and populate it 
    # with the Todo list objects
    queryset = Todo.objects.all()

Schritt 8: Öffnen Sie nun die Datei urls.py und fügen Sie den folgenden Code hinzu.

Python3

from django.contrib import admin
  
# add include to the path
from django.urls import path, include
  
# import views from todo
from todo import views
  
# import routers from the REST framework
# it is neccessary for routing
from rest_framework import routers
  
# create a router object
router = routers.DefaultRouter()
  
# register the router
router.register(r'tasks',views.TodoView, 'task')
  
urlpatterns = [
    path('admin/', admin.site.urls),
  
    # add another path to the url patterns
    # when you visit the localhost:8000/api
    # you should be routed to the django Rest framework
    path('api/', include(router.urls))
  
  
]

Dies ist der letzte Schritt zum Erstellen der REST-API, und wir können jetzt alle CRUD-Vorgänge ausführen. Router ermöglichen uns Abfragen. Wenn wir zum Beispiel zu den „Aufgaben“ gehen, wird die Liste aller Aufgaben zurückgegeben. Sie können auch eine einzelne "Aufgabe" mit einer ID haben , um eine einzelne Aufgabe zurückzugeben, wobei die ID der Primärschlüssel ist.

Lassen Sie uns nun prüfen, ob wir uns in die richtige Richtung bewegen. Führen Sie also den Server aus und navigieren Sie zur folgenden URL:

localhost:8000/api

Wenn alles in Ordnung ist, erhalten wir das folgende Ergebnis:

Wie Sie sehen können, ist unsere API in Betrieb.

Wenn wir nun zu den folgenden Links navigieren, können wir unsere Aufgaben anzeigen und mit ihnen interagieren:

locaLHOST:8000/api/tasks

Frontend (React js):

Lassen Sie uns nun das Frontend für unsere Todo-App erstellen. Führen Sie dazu die folgenden Schritte aus:

Schritt 1: Navigieren Sie zum Hauptprojektverzeichnis (dh django-react-app) und aktivieren Sie die virtuelle Umgebung mit dem folgenden Befehl:

dar\Scripts\activate.bat

Schritt 2: Verwenden Sie nun den folgenden Befehl, um eine Boilerplate der React js-App zu erstellen:

npx create-react-app frontend

Hier steht npx für Node Package Executable. Nachdem die Boilerplate eingerichtet ist, erhalten Sie die folgende Meldung:

Wir brauchen auch etwas UI-Flair für das UI-Design, insbesondere Reactstrap und Bootstrap.

Schritt 3: Verwenden Sie also den folgenden Befehl, um Reactstrap und Bootstrap im Projekt zu installieren:

npm install reactstrap bootstrap

Schritt 4: Wechseln Sie zuerst in den Frontend-Ordner und verwenden Sie den folgenden Befehl, um den React-Server auszuführen, um sicherzustellen, dass alles bis zu diesem Punkt funktioniert:

npm start

Wenn alles in Ordnung ist, erhalten Sie die folgende Seite auf localhost:3000

Schritt 5: Öffnen Sie nun die Datei App.js im Frontend-Ordner. Und löschen Sie den Boilerplate-Code und ändern Sie ihn in den folgenden Code:

Javascript

import "./App.css";
  
function App() {
  return <div className="App"><h2>Welcome to Geeksforgeeks!</h2></div>;
}
  
export default App;

An dieser Stelle sieht das Frontend wie folgt aus:

Wie Sie im obigen Bild sehen können. Alle an der App.js-Datei vorgenommenen Änderungen werden direkt in der Benutzeroberfläche wiedergegeben.

Schritt 6: Nun der Code zur App.js Datei. Kommentare werden dem Code zum besseren Verständnis hinzugefügt.

Javascript

// import Component from the react module
import React, { Component } from "react";
import Modal from "./components/Modal";
import axios from 'axios';  
  
// create a class that extends the component
class App extends Component {
  
  // add a constructor to take props
  constructor(props) {
    super(props);
      
    // add the props here
    this.state = {
      
      // the viewCompleted prop represents the status
      // of the task. Set it to false by default
      viewCompleted: false,
      activeItem: {
        title: "",
        description: "",
        completed: false
      },
        
      // this list stores all the completed tasks
      taskList: []
    };
  }
  
  // Add componentDidMount()
  componentDidMount() {
    this.refreshList();
  }
  
   
  refreshList = () => {
    axios   //Axios to send and receive HTTP requests
      .get("http://localhost:8000/api/tasks/")
      .then(res => this.setState({ taskList: res.data }))
      .catch(err => console.log(err));
  };
  
  // this arrow function takes status as a parameter
  // and changes the status of viewCompleted to true
  // if the status is true, else changes it to false
  displayCompleted = status => {
    if (status) {
      return this.setState({ viewCompleted: true });
    }
    return this.setState({ viewCompleted: false });
  };
  
  // this array function renders two spans that help control
  // the set of items to be displayed(ie, completed or incomplete)
  renderTabList = () => {
    return (
      <div className="my-5 tab-list">
        <span
          onClick={() => this.displayCompleted(true)}
          className={this.state.viewCompleted ? "active" : ""}
        >
          completed
            </span>
        <span
          onClick={() => this.displayCompleted(false)}
          className={this.state.viewCompleted ? "" : "active"}
        >
          Incompleted
            </span>
      </div>
    );
  };
  // Main variable to render items on the screen
  renderItems = () => {
    const { viewCompleted } = this.state;
    const newItems = this.state.taskList.filter(
      (item) => item.completed === viewCompleted
    );
    return newItems.map((item) => (
      <li
        key={item.id}
        className="list-group-item d-flex justify-content-between align-items-center"
      >
        <span
          className={`todo-title mr-2 ${
            this.state.viewCompleted ? "completed-todo" : ""
          }`}
          title={item.description}
        >
          {item.title}
        </span>
        <span>
          <button
            onClick={() => this.editItem(item)}
            className="btn btn-secondary mr-2"
          >
            Edit
          </button>
          <button
            onClick={() => this.handleDelete(item)}
            className="btn btn-danger"
          >
            Delete
          </button>
        </span>
      </li>
    ));
  };
  
  toggle = () => {
    //add this after modal creation
    this.setState({ modal: !this.state.modal });
  };
  handleSubmit = (item) => {
    this.toggle();
    alert("save" + JSON.stringify(item));
  };
  
  // Submit an item
  handleSubmit = (item) => {
    this.toggle();
    if (item.id) {
      // if old post to edit and submit
      axios
        .put(`http://localhost:8000/api/tasks/${item.id}/`, item)
        .then((res) => this.refreshList());
      return;
    }
    // if new post to submit
    axios
      .post("http://localhost:8000/api/tasks/", item)
      .then((res) => this.refreshList());
  };
  
  // Delete item
  handleDelete = (item) => {
    axios
      .delete(`http://localhost:8000/api/tasks/${item.id}/`)
      .then((res) => this.refreshList());
  };
  handleDelete = (item) => {
    alert("delete" + JSON.stringify(item));
  };
  
  // Create item
  createItem = () => {
    const item = { title: "", description: "", completed: false };
    this.setState({ activeItem: item, modal: !this.state.modal });
  };
  
  //Edit item
  editItem = (item) => {
    this.setState({ activeItem: item, modal: !this.state.modal });
  };
  
  // Start by visual effects to viewer
  render() {
    return (
      <main className="content">
        <h1 className="text-success text-uppercase text-center my-4">
          GFG Task Manager
        </h1>
        <div className="row ">
          <div className="col-md-6 col-sm-10 mx-auto p-0">
            <div className="card p-3">
              <div className="">
                <button onClick={this.createItem} className="btn btn-info">
                  Add task
                </button>
              </div>
              {this.renderTabList()}
              <ul className="list-group list-group-flush">
                {this.renderItems()}
              </ul>
            </div>
          </div>
        </div>
        {this.state.modal ? (
          <Modal
            activeItem={this.state.activeItem}
            toggle={this.toggle}
            onSave={this.handleSubmit}
          />
        ) : null}
      </main>
    );
  }
}
export default App;

Schritt 7: Öffnen Sie nun die Datei Index.css , löschen Sie das darin enthaltene CSS und fügen Sie das folgende CSS in die Datei ein:

CSS

.todo-title {
  cursor: pointer;
}
.completed-todo {
  text-decoration: line-through;
}
.tab-list > span {
  padding: 5px 8px;
  border: 1px solid rgb(7, 167, 68);
  border-radius: 10px;
  margin-right: 5px;
  cursor: pointer;
}
.tab-list > span.active {
  background-color: rgb(6, 139, 12);
  color: #fff;
}

Schritt 8: Erstellen Sie nun im src -Verzeichnis einen neuen Ordner mit dem Namen „Components“ und fügen Sie eine Datei Modal.js hinzu. Fügen Sie dann den folgenden Code hinzu.

Javascript

import React, { Component } from "react";
  
// importing all of these classes from reactstrap module
import {
  Button,
  Modal,
  ModalHeader,
  ModalBody,
  ModalFooter,
  Form,
  FormGroup,
  Input,
  Label
} from "reactstrap";
  
// build a class base component
class CustomModal extends Component {
  constructor(props) {
    super(props);
    this.state = {
      activeItem: this.props.activeItem
    };
  }
  // changes handler to check if a checkbox is checed or not
  handleChange = e => {
    let { name, value } = e.target;
    if (e.target.type === "checkbox") {
      value = e.target.checked;
    }
    const activeItem = { ...this.state.activeItem, [name]: value };
    this.setState({ activeItem });
  };
  
  // rendering modal in the custommodal class received toggle and on save as props,
  render() {
    const { toggle, onSave } = this.props;
    return (
      <Modal isOpen={true} toggle={toggle}>
        <ModalHeader toggle={toggle}> Task Item </ModalHeader>
        <ModalBody>
          
          <Form>
  
            {/* 3 formgroups
            1 title label */}
            <FormGroup>
              <Label for="title">Title</Label>
              <Input
                type="text"
                name="title"
                value={this.state.activeItem.title}
                onChange={this.handleChange}
                placeholder="Enter Task Title"
              />
            </FormGroup>
  
            {/* 2 description label */}
            <FormGroup>
              <Label for="description">Description</Label>
              <Input
                type="text"
                name="description"
                value={this.state.activeItem.description}
                onChange={this.handleChange}
                placeholder="Enter Task Description"
              />
            </FormGroup>
  
            {/* 3 completed label */}
            <FormGroup check>
              <Label for="completed">
                <Input
                  type="checkbox"
                  name="completed"
                  checked={this.state.activeItem.completed}
                  onChange={this.handleChange}
                />
                Completed
              </Label>
            </FormGroup>
          </Form>
        </ModalBody>
        {/* create a modal footer */}
        <ModalFooter>
          <Button color="success" onClick={() => onSave(this.state.activeItem)}>
            Save
          </Button>
        </ModalFooter>
      </Modal>
    );
  }
}
export default CustomModal

Schritt 10: Nehmen Sie die Änderungen an der Datei index.js wie folgt vor:

Javascript

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
  
// importing css stylesheet to use the bootstrap class
// add this line only in this file
import "bootstrap/dist/css/bootstrap.min.css"; 
  
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

API-Verbindung:

Damit wir Requestsn an die API-Endpunkte auf dem Backend-Server von Django stellen können, müssen wir Axios installieren. Verwenden Sie den folgenden Befehl im Frontend-Ordner, um Axios zu installieren:

npm install axios

Ausgabe:

Gratulation!!. An diesem Punkt haben Sie erfolgreich eine Fullstack Django-React-App erstellt und das Django-REST-Framework verwendet, um die Kommunikation zwischen Frontend und Backend herzustellen.