Wie man mit Django und React unter Ubuntu 18.04 eine moderne Webanwendung für das Kundeninformationsmanagement erstellt

0 Aktien
0
0
0
0

Einführung

Menschen nutzen eine Vielzahl von Geräten, um sich mit dem Internet zu verbinden und im Web zu surfen. Daher müssen Anwendungen von verschiedenen Standorten aus zugänglich sein. Für herkömmliche Websites ist eine responsive Benutzeroberfläche meist ausreichend, komplexere Anwendungen erfordern jedoch häufig andere Techniken und Architekturen. Dazu gehören separate Backend- und Frontend-REST-Anwendungen, die als clientseitige Webanwendungen, progressive Webanwendungen (PWAs) oder native mobile Apps ausgeführt werden können.

Zu den Werkzeugen, die Sie beim Erstellen komplexerer Anwendungen verwenden können, gehören:

  • React ist ein JavaScript-Framework, mit dem Entwickler Web- und native Seiten für ihre REST-API-Backends erstellen können.
  • Django ist ein kostenloses und quelloffenes Python-Webframework, das dem Model-View-Controller (MVC)-Softwarearchitekturmuster folgt.
  • Django REST Framework, ein leistungsstarkes und flexibles Toolkit zum Erstellen von REST-APIs in Django.

In diesem Tutorial entwickeln Sie eine moderne Webanwendung mit separatem REST-API-Backend und -Frontend mithilfe von React, Django und dem Django REST Framework. Durch die Verwendung von React mit Django profitieren Sie von den neuesten Fortschritten in JavaScript und der Frontend-Entwicklung. Anstatt eine Django-Anwendung mit integrierter Template-Engine zu erstellen, nutzen Sie React als UI-Bibliothek mit einem virtuellen Document Object Model (DOM), einem deklarativen Ansatz und Komponenten, die Datenänderungen schnell rendern.

Die Webanwendung, die Sie entwickeln werden, speichert Kundendatensätze in einer Datenbank und kann als Ausgangspunkt für eine CRM-Anwendung dienen. Nach Fertigstellung können Sie die Daten über eine mit Bootstrap 4 gestaltete React-Oberfläche lesen, aktualisieren und löschen.

Voraussetzungen

Um dieses Tutorial abzuschließen, benötigen Sie Folgendes:

  • Ein Entwicklungsrechner mit Ubuntu 18.04.
  • Python 3, pip und venv werden auf Ihrem Rechner installiert, indem Sie die Schritte 1 und 2 der Anleitung „So installieren Sie Python 3 und richten eine lokale Entwicklungsumgebung unter Ubuntu 18.04 ein“ befolgen.
  • Node.js 6+ und npm 5.2 oder höher sind auf Ihrem Rechner installiert. Sie können beides installieren, indem Sie den Anweisungen unter „Node.js unter Ubuntu 18.04 installieren“ im Abschnitt „Installation über PPA“ folgen.

Schritt 1 – Erstellen Sie eine virtuelle Python-Umgebung und installieren Sie die Abhängigkeiten

In diesem Schritt erstellen wir eine virtuelle Umgebung und installieren die erforderlichen Abhängigkeiten für unsere Anwendung, darunter Django, das Django REST Framework und django-cors-headers.

Unsere Anwendung nutzt zwei separate Entwicklungsserver für Django und React. Diese laufen auf unterschiedlichen Ports und fungieren als zwei separate Domains. Daher müssen wir Cross-Resource Sharing (CORS) aktivieren, damit HTTP-Anfragen von React an Django gesendet werden können, ohne vom Browser blockiert zu werden.

Wechseln Sie in Ihr Home-Verzeichnis und erstellen Sie eine virtuelle Umgebung mithilfe des Python 3-Moduls venv:

cd ~
python3 -m venv ./env

Aktivieren Sie die erstellte virtuelle Umgebung mithilfe der Quelle:

source env/bin/activate

Installieren Sie anschließend die Projektabhängigkeiten mit pip. Dazu gehören folgende:

  • Django: Web-Framework für das Projekt.
  • Django REST Framework: Eine Drittanbieteranwendung, die REST-APIs mit Django erstellt.
  • django-cors-headers: Ein Paket, das CORS aktiviert.

Installieren Sie das Django-Framework:

pip install django djangorestframework django-cors-headers

Durch die Installation der Projektabhängigkeiten können Sie ein Django-Projekt und ein React-Frontend erstellen.

Schritt 2 – Ein Django-Projekt erstellen

In diesem Schritt generieren wir das Django-Projekt mithilfe der folgenden Befehle und Tools:

django-admin startproject-name: django-admin ist ein Kommandozeilen-Tool zur Ausführung von Aufgaben mit Django. Der Befehl startproject erstellt ein neues Django-Projekt.

`python manager.py startapp myapp`: `manager.py` ist ein Hilfsskript, das automatisch zu jedem Django-Projekt hinzugefügt wird und verschiedene administrative Aufgaben übernimmt: das Erstellen neuer Anwendungen, das Migrieren von Datenbanken und das lokale Bereitstellen des Django-Projekts. Der Befehl `startapp` erstellt eine Django-Anwendung innerhalb des Django-Projekts. In Django bezeichnet der Begriff „Anwendung“ ein Python-Paket, das einem Projekt bestimmte Funktionen bereitstellt.

Um zu beginnen, erstellen Sie ein Django-Projekt mit django-admin startproject. Wir nennen unser Projekt djangoreactproject.

django-admin startproject djangoreactproject

Bevor wir fortfahren, sehen wir uns die Verzeichnisstruktur des Django-Projekts mithilfe des Befehls „tree“ an.

Wechseln Sie im Stammverzeichnis Ihres Projekts in den Ordner „djangoreactproject“ und führen Sie den Befehl „tree“ aus:

cd ~/djangoreactproject
tree

Sie sehen folgende Ausgabe:

Output
├── djangoreactproject
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py

Der Ordner ~/djangoreactproject ist das Stammverzeichnis des Projekts. In diesem Ordner befinden sich mehrere Dateien, die für Ihre Arbeit wichtig sind:

  • manager.py: Ein Hilfsskript, das eine Reihe administrativer Aufgaben ausführt.
  • settings.py: Die Hauptkonfigurationsdatei eines Django-Projekts, in der Sie Projekteinstellungen ändern können. Diese Einstellungen umfassen Variablen wie INSTALLED_APPS, eine Liste von Zeichenketten, die die aktiven Anwendungen Ihres Projekts angeben. Weitere Informationen zu den verfügbaren Einstellungen finden Sie in der Django-Dokumentation.
  • urls.py: Diese Datei enthält eine Liste von URL-Mustern und zugehörigen Views. Jedes Muster stellt eine Beziehung zwischen einer URL und der für diese URL aufzurufenden Funktion her. Weitere Informationen zu URLs und Views finden Sie in unserem Tutorial zur Erstellung von Django-Views.

Der erste Schritt bei der Arbeit mit dem Projekt besteht darin, die im vorherigen Schritt installierten Pakete, einschließlich des Django REST Frameworks und des Django CORS-Pakets, zu konfigurieren, indem wir sie zu settings.py hinzufügen. Öffnen Sie die Datei mit nano oder Ihrem bevorzugten Editor:

nano ~/djangoreactproject/djangoreactproject/settings.py

Gehen Sie zu den Einstellungen INSTALLED_APPS und fügen Sie die Anwendungen rest_framework und corsheaders am Ende der Liste hinzu:

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

Fügen Sie als Nächstes die Middleware corsheaders.middleware.CorsMiddleware aus dem zuvor installierten CORS-Paket zur MIDDLEWARE-Konfiguration hinzu. Diese Konfiguration ist eine Liste von Middleware-Klassen, Python-Klassen, die Code enthalten, der bei jeder Anfrage oder Antwort Ihrer Webanwendung ausgeführt wird.

...
MIDDLEWARE = [
...
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware'
]

Als Nächstes können Sie CORS aktivieren. Die Einstellung `CORS_ORIGIN_ALLOW_ALL` legt fest, ob CORS für alle Domains erlaubt sein soll, und `CORS_ORIGIN_WHITELIST` ist ein Python-Tupel mit den zulässigen URLs. Da der React-Entwicklungsserver in unserem Fall unter `http://localhost:3000` läuft, fügen wir die neuen Einstellungen `CORS_ORIGIN_ALLOW_ALL = False` und `CORS_ORIGIN_WHITELIST('localhost:3000',)` zu unserer `settings.py`-Datei hinzu. Fügen Sie diese Einstellungen an beliebiger Stelle in der Datei ein.

...
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'localhost:3000',
)
...

Weitere Konfigurationsoptionen finden Sie in der Dokumentation zu django-cors-headers.

Speichern Sie die Datei und beenden Sie den Editor, wenn Sie fertig sind.

Erstellen Sie im Verzeichnis ~/djangoreactproject eine neue Django-Anwendung namens customers:

python manage.py startapp customers

Dies umfasst Client-Management-Modelle und -Ansichten. Modelle definieren die Felder und Verhaltensweisen der Daten unserer Anwendung, während Ansichten es unserer Anwendung ermöglichen, Webanfragen ordnungsgemäß zu verarbeiten und die erforderlichen Antworten zurückzugeben.

Fügen Sie diese Anwendung als Nächstes der Liste der installierten Anwendungen in der settings.py-Datei Ihres Projekts hinzu, damit Django sie als Teil des Projekts erkennt. Öffnen Sie settings.py erneut:

nano ~/djangoreactproject/djangoreactproject/settings.py

Kundenanwendung hinzufügen:

...
INSTALLED_APPS = [
...
'rest_framework',
'corsheaders',
'customers'
]
...

Migrieren Sie anschließend die Datenbank und starten Sie den lokalen Entwicklungsserver. Migrationen sind Djangos Methode, Änderungen an Ihren Modellen in das Datenbankschema zu übernehmen. Diese Änderungen können beispielsweise das Hinzufügen eines Feldes oder das Löschen eines Modells umfassen. Weitere Informationen zu Modellen und Migrationen finden Sie unter „Django-Modelle erstellen“.

Datenbankübertragung:

python manage.py migrate

Starten Sie den lokalen Entwicklungsserver:

python manage.py runserver

Sie sehen eine Ausgabe, die in etwa wie folgt aussieht:

Output
Performing system checks...
System check identified no issues (0 silenced).
October 22, 2018 - 15:14:50
Django version 2.1.2, using settings 'djangoreactproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Ihre Webanwendung wird unter http://127.0.0.1:8000 erreichbar sein. Wenn Sie diese Adresse in Ihrem Webbrowser aufrufen, sollte die folgende Seite angezeigt werden:

Lassen Sie das Programm an dieser Stelle laufen und öffnen Sie ein neues Terminal, um die Entwicklung des Projekts fortzusetzen.

Schritt 3 – React-Frontend erstellen

In diesem Abschnitt werden wir die Frontend-Anwendung unseres Projekts mit React erstellen.

React bietet ein offizielles Tool, mit dem sich React-Projekte schnell generieren lassen, ohne Webpack direkt konfigurieren zu müssen. Webpack ist ein Modulbundler, der Webressourcen wie JavaScript-Code, CSS und Bilder bündelt. Normalerweise müssten Sie verschiedene Konfigurationsoptionen festlegen, bevor Sie Webpack verwenden können. Dank des Tools Create-react-app müssen Sie sich jedoch nicht direkt mit Webpack auseinandersetzen, es sei denn, Sie benötigen mehr Kontrolle. Zum Ausführen von Create-react-app können Sie npx verwenden, ein Tool, das mit npm gepackte Binärdateien ausführt.

Stellen Sie in Ihrem zweiten Terminal sicher, dass Sie sich in Ihrem Projektverzeichnis befinden:

cd ~/djangoreactproject

Erstelle ein React-Projekt namens frontend mit create-react-app und npx:

npx create-react-app frontend

Navigieren Sie als Nächstes in Ihrer React-App und starten Sie den Entwicklungsserver:

cd ~/djangoreactproject/frontend
npm start

Ihre Anwendung wird von http://localhost:3000/ ausgeführt:

Lassen Sie den React-Entwicklungsserver laufen und öffnen Sie ein weiteres Terminalfenster, um fortzufahren.

Um die Verzeichnisstruktur des gesamten Projekts an dieser Stelle anzuzeigen, wechseln Sie in den Stammordner und führen Sie den Befehl „tree“ erneut aus:

cd ~/djangoreactproject
tree

Sie werden eine Struktur wie diese sehen:

Output
├── customers
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── djangoreactproject
│ ├── __init__.py
│ ├── __pycache__
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── frontend
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ ├── README.md
│ ├── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
│ └── yarn.lock
└── manage.py

Unsere App verwendet Bootstrap 4 für das Design der React-Oberfläche. Daher fügen wir die CSS-Einstellungen in die Datei frontend/src/App.css ein. Öffnen Sie die Datei:

nano ~/djangoreactproject/frontend/src/App.css

Fügen Sie den folgenden Eintrag am Anfang der Datei hinzu. Sie können den vorhandenen Inhalt der Datei löschen, dies ist jedoch nicht notwendig:

@import 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css';

Hierbei handelt es sich bei @import um eine CSS-Direktive, die dazu dient, Stilregeln aus anderen Stylesheets zu importieren.

Nachdem wir nun sowohl die Backend- als auch die Frontend-Anwendung erstellt haben, erstellen wir das Kundenmodell und einige Demodaten.

Schritt 4 – Kundenmodell und erste Daten erstellen

Nachdem wir die Django-Anwendung und die React-Instanz erstellt haben, erstellen wir als Nächstes das Kundenmodell. Dieses repräsentiert die Datenbanktabelle, die die Kundeninformationen enthält. SQL ist nicht erforderlich, da der Django Object Relational Mapper (ORM) Datenbankoperationen durchführt, indem er Python-Klassen und -Variablen SQL-Tabellen und -Spalten zuordnet. Dadurch abstrahiert der Django ORM die SQL-Interaktionen mit der Datenbank über eine Python-Schnittstelle.

Aktivieren Sie Ihre virtuelle Umgebung wieder:

cd ~
source env/bin/activate

Wechseln Sie in das Verzeichnis „clients“ und öffnen Sie die Datei „models.py“, eine Python-Datei, die die Modelle Ihrer Anwendung enthält:

cd ~/djangoreactproject/customers/
nano models.py

Die Datei wird folgenden Inhalt enthalten:

from django.db import models
# Create your models here.

Die Customer-Modell-API ist dank der `import models from django.db`-Anweisung bereits in der Datei enthalten. Nun fügen Sie die Klasse `Customer` hinzu, die von `models.Model` erbt. Jedes Modell in Django ist eine Python-Klasse, die von `django.db.models.Model` erbt.

Das Kundenmodell wird folgende Datenbankfelder enthalten:

  • Vorname – Vorname des Kunden.
  • Nachname – Nachname des Kunden.
  • E-MAIL – E-Mail-Adresse des Kunden.
  • Telefon – Telefonnummer des Kunden.
  • ADRESSE – Kundenadresse.
  • Beschreibung – Kundenbeschreibung.
  • erstellen bei – Das Datum, an dem der Kunde hinzugefügt wurde.

Wir fügen außerdem die Funktion `__str__()` hinzu, die festlegt, wie das Modell angezeigt wird. In unserem Fall ist es der Vorname des Kunden. Weitere Informationen zum Erstellen von Klassen und Definieren von Objekten finden Sie unter „Erstellen von Klassen und Definieren von Objekten in Python 3“.

Fügen Sie der Datei folgenden Code hinzu:

from django.db import models
class Customer(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

Als Nächstes migrieren Sie die Datenbank, um die Datenbanktabellen zu erstellen. Der Befehl `makemigrations` erstellt die Migrationsdateien, in denen die Modelländerungen hinzugefügt werden, und der Befehl `migrate` wendet die Änderungen aus den Migrationsdateien auf die Datenbank an.

Wechseln Sie zurück zum Projektstammverzeichnis:

cd ~/djangoreactproject

Um Migrationsdateien zu erstellen, führen Sie Folgendes aus:

python manage.py makemigrations

Sie erhalten eine Ausgabe wie diese:

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

Wenden Sie diese Änderungen auf die Datenbank an:

python manage.py migrate

Sie sehen eine Ausgabe, die eine erfolgreiche Übertragung anzeigt:

Output
Operations to perform:
Apply all migrations: admin, auth, contenttypes, customers, sessions
Running migrations:
Applying customers.0001_initial... OK

Als Nächstes erstellen Sie mithilfe einer Datenübertragungsdatei die initialen Kundendaten. Eine Datenübertragungsdatei ist eine Migration, die Daten zur Datenbank hinzufügt oder ändert. Erstellen Sie eine leere Datenübertragungsdatei für die Anwendung „Kunden“:

python manage.py makemigrations --empty --name customers customers

Sie sehen die folgende Bestätigung mit dem Namen Ihrer Migrationsdatei:

Output
Migrations for 'customers':
customers/migrations/0002_customers.py

Beachten Sie, dass Ihre Migrationsdatei den Namen 0002_customers.py trägt.

Navigieren Sie als Nächstes zum Migrationsordner der Clientanwendung:

cd ~/djangoreactproject/customers/migrations

Öffnen Sie die erstellte Migrationsdatei:

nano 0002_customers.py

Dies ist der ursprüngliche Inhalt der Datei:

from django.db import migrations

class Migration(migrations.Migration):
dependencies = [
('customers', '0001_initial'),
]
operations = [
]

Die Importanweisung importiert die Migrations API, eine Django-API zum Erstellen von Migrationen, aus django.db, einem integrierten Paket, das Klassen für die Arbeit mit Datenbanken enthält.

Die Klasse `Migration` ist eine Python-Klasse, die die Operationen beschreibt, die bei der Migration einer Datenbank durchgeführt werden. Sie erweitert `migrations.Migration` und verfügt über zwei Listen:

  • Abhängigkeiten: Beinhaltet abhängige Migrationen.
  • Operationen: Enthält Operationen, die durch Anwenden von Migrationen ausgeführt werden.

Fügen Sie als Nächstes eine Methode zum Erstellen der Testkundendaten hinzu. Fügen Sie die folgende Methode vor der Definition der Migrationsklasse hinzu:

...
def create_data(apps, schema_editor):
Customer = apps.get_model('customers', 'Customer')
Customer(first_name="Customer 001", last_name="Customer 001", email="[email protected]", phone="00000000", address="Customer 000 Address", description= "Customer 001 description").save()
...

Bei dieser Methode nehmen wir die Kundenklasse unserer Kundenanwendung und erstellen einen Testkunden, der in die Datenbank eingefügt wird.

Um die Klasse „Customer“ zu erhalten, mit der wir neue Kunden anlegen können, verwenden wir die Methode „get_model()“ des Objekts „apps“. Das Objekt „apps“ repräsentiert die Liste der installierten Anwendungen und ihrer Datenbankmodelle.

Wenn wir die Methode `RunPython()` verwenden, um `create_data()` auszuführen, wird das `apps`-Objekt übergeben. Fügen Sie die Methode `migrations.RunPython()` der leeren Operationsliste hinzu:

...
operations = [
migrations.RunPython(create_data),
]

RunPython() ist Teil der Migrations-API und ermöglicht das Ausführen von benutzerdefiniertem Python-Code innerhalb einer Migration. Unsere Operationsliste legt fest, dass diese Methode beim Anwenden der Migration ausgeführt wird.

Hier ist die vollständige Datei:

from django.db import migrations

def create_data(apps, schema_editor):
Customer = apps.get_model('customers', 'Customer')
Customer(first_name="Customer 001", last_name="Customer 001", email="[email protected]", phone="00000000", address="Customer 000 Address", description= "Customer 001 description").save()

class Migration(migrations.Migration):
dependencies = [
('customers', '0001_initial'),
]
operations = [
migrations.RunPython(create_data),
]

Weitere Informationen zur Datenmigration finden Sie in der Django-Dokumentation zur Datenmigration.

Um Ihre Datenbank zu verschieben, wechseln Sie zunächst zurück in den Hauptordner Ihres Projekts:

cd ~/djangoreactproject

Migrieren Sie Ihre Datenbank, um Testdaten zu erstellen:

python manage.py migrate

Sie sehen eine Ausgabe, die die Migration bestätigt:

Output
Operations to perform:
Apply all migrations: admin, auth, contenttypes, customers, sessions
Running migrations:
Applying customers.0002_customers... OK

Nachdem das Kundenmodell und die Repräsentationsdaten erstellt wurden, können wir mit dem Aufbau der REST-API fortfahren.

Schritt 5 – REST-API erstellen

In diesem Schritt erstellen wir eine REST-API mit dem Django REST-Framework. Wir erstellen mehrere verschiedene API-Views. Ein API-View ist eine Funktion, die eine API-Anfrage oder einen API-Aufruf verarbeitet, während ein API-Endpunkt eine eindeutige URL ist, die den Kontaktpunkt zum REST-System darstellt. Wenn ein Benutzer beispielsweise eine GET-Anfrage an einen API-Endpunkt sendet, ruft Django die entsprechende Funktion oder API-View auf, um die Anfrage zu bearbeiten und mögliche Ergebnisse zurückzugeben.

Wir werden auch Serialisierer verwenden. Ein Serialisierer im Django REST Framework ermöglicht die Konvertierung komplexer Modellinstanzen und QuerySets in das JSON-Format für die API-Nutzung. Die Serialisiererklasse kann auch in umgekehrter Richtung arbeiten und bietet Mechanismen zum Parsen und Trennen von Daten in Django-Modellen und QuerySets.

Unsere API-Endpunkte umfassen:

  • api/customers: Dieser Endpunkt dient zum Anlegen von Kunden und zum Abrufen paginierter Kundenlisten.
  • api/customers/ Dieser Endpunkt dient zum Abrufen, Aktualisieren und Löschen einzelner Kunden anhand des Primärschlüssels oder der ID.

Wir erstellen außerdem URLs in der urls.py-Datei des Projekts für die entsprechenden Endpunkte (d. h. api/customers und api/customers/). ).

Beginnen wir mit der Erstellung der Serialisierungsklasse für unser Client-Modell.

Füge eine Serialisierungsklasse hinzu.

Die Erstellung einer Serialisierungsklasse für unser Kundenmodell ist unerlässlich, um Kundeninstanzen und QuerySets in und aus JSON zu konvertieren. Um die Serialisierungsklasse zu erstellen, erstellen Sie zunächst eine Datei namens serializers.py innerhalb der Anwendung „Customers“.

cd ~/djangoreactproject/customers/
nano serializers.py

Fügen Sie den folgenden Code hinzu, um die API-Seriennummer und das Client-Modell zu importieren:

from rest_framework import serializers
from .models import Customer

Erstellen Sie als Nächstes eine Serialisierungsklasse, die von Serializers.ModelSerializer erbt und die zu serialisierenden Felder angibt:

...
class CustomerSerializer(serializers.ModelSerializer):

class Meta:
model = Customer
fields = ('pk','first_name', 'last_name', 'email', 'phone','address','description')

Die Meta-Klasse legt das Modell und die Felder für die Serialisierung fest: pk, first_name, last_name, email, phone, address, description.

Hier ist der vollständige Inhalt der Datei:

from rest_framework import serializers
from .models import Customer

class CustomerSerializer(serializers.ModelSerializer):

class Meta:
model = Customer
fields = ('pk','first_name', 'last_name', 'email', 'phone','address','description')

Nachdem wir nun unsere Serialisierungsklasse erstellt haben, können wir API-Ansichten hinzufügen.

Hinzufügen von API-Ansichten

In diesem Abschnitt erstellen wir API-Ansichten für unsere Anwendung, die von Django aufgerufen werden, wenn der Benutzer den Endpunkt besucht, der der Ansichtsfunktion entspricht.

~/djangoreactproject/customers/views.py Offen:

nano ~/djangoreactproject/customers/views.py

Löschen Sie die vorhandenen Einträge und fügen Sie die folgenden Importe hinzu:

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 *

Wir importieren die von uns erstellte Serialisierung zusammen mit dem Client-Modell und den Django REST Framework APIs.

Als Nächstes fügen Sie die Ansicht hinzu, um POST- und GET-HTTP-Anfragen zu verarbeiten:

...
@api_view(['GET', 'POST'])
def customers_list(request):
"""
List customers, or create a new customer.
"""
if request.method == 'GET':
data = []
nextPage = 1
previousPage = 1
customers = Customer.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(customers, 10)
try:
data = paginator.page(page)
except PageNotAnInteger:
data = paginator.page(1)
except EmptyPage:
data = paginator.page(paginator.num_pages)
serializer = CustomerSerializer(data,context={'request': request} ,many=True)
if data.has_next():
nextPage = data.next_page_number()
if data.has_previous():
previousPage = data.previous_page_number()
return Response({'data': serializer.data , 'count': paginator.count, 'numpages' : paginator.num_pages, 'nextlink': '/api/customers/?page=' + str(nextPage), 'prevlink': '/api/customers/?page=' + str(previousPage)})
elif request.method == 'POST':
serializer = CustomerSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Zunächst verwenden wir den Dekorator `@api_view(['GET', 'POST'])`, um eine API-Ansicht zu erstellen, die GET- und POST-Anfragen entgegennehmen kann. Ein Dekorator ist eine Funktion, die eine andere Funktion als Parameter nimmt und diese dynamisch erweitert.

Im Methodenkörper verwenden wir die Variable request.method, um die aktuelle HTTP-Methode zu überprüfen und die entsprechende Logik je nach Anfragetyp auszuführen:

  • Bei einer GET-Anfrage paginiert diese Methode die Daten mithilfe des Django-Paginators und gibt nach der Serialisierung die erste Datenseite, die Anzahl der verfügbaren Kunden, die Anzahl der verfügbaren Seiten sowie Links zur vorherigen und nächsten Seite zurück. Der Paginator ist eine integrierte Django-Klasse, die eine Datenliste in Seiten unterteilt und Methoden für den Zugriff auf die Elemente jeder Seite bereitstellt.
  • Bei einer POST-Anfrage serialisiert die Methode die empfangenen Clientdaten und ruft anschließend die `save()`-Methode des Serialisierungsobjekts auf. Sie gibt dann ein `Response`-Objekt (eine Instanz von `HttpResponse`) mit dem Statuscode 201 zurück. Jedes erstellte Profil ist für die Rückgabe eines `HttpResponse`-Objekts verantwortlich. Die `save()`-Methode speichert die serialisierten Daten in der Datenbank.

Weitere Informationen zu HttpResponse und Views finden Sie in dieser Diskussion über die Erstellung von View-Funktionen.

Fügen Sie nun die API-Ansicht hinzu, die für die Verarbeitung von GET-, PUT- und DELETE-Anfragen zum Abrufen, Aktualisieren und Löschen von Kunden anhand des Primärschlüssels zuständig ist:

...
@api_view(['GET', 'PUT', 'DELETE'])
def customers_detail(request, pk):
"""
Retrieve, update or delete a customer by id/pk.
"""
try:
customer = Customer.objects.get(pk=pk)
except Customer.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

if request.method == 'GET':
serializer = CustomerSerializer(customer,context={'request': request})
return Response(serializer.data)

elif request.method == 'PUT':
serializer = CustomerSerializer(customer, data=request.data,context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

elif request.method == 'DELETE':
customer.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

Diese Methode ist mit @api_view(['GET', 'PUT', 'DELETE']) gekennzeichnet, um anzuzeigen, dass es sich um eine API-Ansicht handelt, die GET-, PUT- und DELETE-Anfragen akzeptieren kann.

Die Prüfung des Felds request.method verifiziert die Anfragemethode und ruft je nach Wert die korrekte Logik auf:

  • Bei einer GET-Anfrage werden die Clientdaten serialisiert und mithilfe eines Response-Objekts gesendet.
  • Bei einer PUT-Anfrage erstellt diese Methode einen Serialisierer für die neuen Clientdaten. Anschließend ruft die Methode `save()` das erstellte Serialisiererobjekt auf. Abschließend wird ein Antwortobjekt mit dem aktualisierten Client gesendet.
  • Handelt es sich um eine DELETE-Anfrage, ruft die delete()-Methode die delete()-Methode des Client-Objekts auf, um dieses zu löschen, und gibt anschließend ein Response-Objekt ohne Daten zurück.

Die fertige Datei sieht folgendermaßen aus:

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 *


@api_view(['GET', 'POST'])
def customers_list(request):
"""
List customers, or create a new customer.
"""
if request.method == 'GET':
data = []
nextPage = 1
previousPage = 1
customers = Customer.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(customers, 5)
try:
data = paginator.page(page)
except PageNotAnInteger:
data = paginator.page(1)
except EmptyPage:
data = paginator.page(paginator.num_pages)

serializer = CustomerSerializer(data,context={'request': request} ,many=True)
if data.has_next():
nextPage = data.next_page_number()
if data.has_previous():
previousPage = data.previous_page_number()

return Response({'data': serializer.data , 'count': paginator.count, 'numpages' : paginator.num_pages, 'nextlink': '/api/customers/?page=' + str(nextPage), 'prevlink': '/api/customers/?page=' + str(previousPage)})

elif request.method == 'POST':
serializer = CustomerSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def customers_detail(request, pk):
"""
Retrieve, update or delete a customer by id/pk.
"""
try:
customer = Customer.objects.get(pk=pk)
except Customer.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

if request.method == 'GET':
serializer = CustomerSerializer(customer,context={'request': request})
return Response(serializer.data)

elif request.method == 'PUT':
serializer = CustomerSerializer(customer, data=request.data,context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

elif request.method == 'DELETE':
customer.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

Nun können wir mit der Erstellung unserer Endpunkte fortfahren.

Hinzufügen von API-Endpunkten

Nun erstellen wir die API-Endpunkte: api/customers/ zum Abfragen und Erstellen von Kunden und api/customers/ Einzelne Kunden anhand ihres Schlüssels abrufen, aktualisieren oder löschen.

Öffne ~/djangoreactproject/djangoreactproject/urls.py:

nano ~/djangoreactproject/djangoreactproject/urls.py

Lassen Sie den vorhandenen Inhalt unverändert, fügen Sie aber den Import zur Kundenansicht oben in der Datei hinzu:

from django.contrib import admin
from django.urls import path
from customers import views
from django.conf.urls import url

Dann die URLs api/customers/ und api/customers/ Fügen Sie der Liste der URL-Muster, die die Anwendungs-URLs enthalten, Folgendes hinzu:

...

urlpatterns = [
path('admin/', admin.site.urls),
url(r'^api/customers/$', views.customers_list),
url(r'^api/customers/(?P<pk>[0-9]+)$', views.customers_detail),
]

Nachdem die REST-Endpunkte erstellt wurden, schauen wir uns nun an, wie wir sie nutzen können.

Schritt 6 – Nutzung der REST-API mit Axios

In diesem Schritt installieren wir Axios, den HTTP-Client, den wir für API-Aufrufe verwenden werden. Außerdem erstellen wir eine Klasse, um die von uns erstellten API-Endpunkte zu nutzen.

Deaktivieren Sie zunächst Ihre virtuelle Umgebung:

deactivate

Wechseln Sie anschließend in Ihren Frontend-Ordner:

cd ~/djangoreactproject/frontend

Installieren Sie axios über npm mit folgendem Befehl:

npm install axios --save

Die Option „–save“ fügt die Axios-Abhängigkeit zur package.json-Datei Ihrer Anwendung hinzu.

Als Nächstes erstellen wir eine JavaScript-Datei namens CustomersService.js, die den Code zum Aufrufen der REST-APIs enthält. Diese Datei erstellen wir im Ordner „src“, in dem sich der Anwendungscode unseres Projekts befindet.

cd src
nano CustomersService.js

Fügen Sie den folgenden Code hinzu, der Methoden zur Verbindung mit der Django REST API enthält:

import axios from 'axios';
const API_URL = 'http://localhost:8000';

export default class CustomersService{

constructor(){}


getCustomers() {
const url = `${API_URL}/api/customers/`;
return axios.get(url).then(response => response.data);
}
getCustomersByURL(link){
const url = `${API_URL}${link}`;
return axios.get(url).then(response => response.data);
}
getCustomer(pk) {
const url = `${API_URL}/api/customers/${pk}`;
return axios.get(url).then(response => response.data);
}
deleteCustomer(customer){
const url = `${API_URL}/api/customers/${customer.pk}`;
return axios.delete(url);
}
createCustomer(customer){
const url = `${API_URL}/api/customers/`;
return axios.post(url,customer);
}
updateCustomer(customer){
const url = `${API_URL}/api/customers/${customer.pk}`;
return axios.put(url,customer);
}
}

Die Klasse CustomersService ruft die folgenden Axios-Methoden auf:

  • getCustomers(): Ruft die erste Seite der Kunden ab.
  • getCustomersByURL(): Ruft Kunden anhand ihrer URL ab. Dadurch können Sie auf nachfolgende Kundenseiten zugreifen, indem Sie Links wie /api/customers/?page=2 übergeben.
  • getCustomer(): Ruft den Kunden anhand des Primärschlüssels ab.
  • createCustomer(): Erstellt einen Kunden.
  • updateCustomer(): Aktualisiert einen Kunden.
  • deleteCustomer(): Löscht einen Kunden.

Wir können unsere API-Daten nun in der React-Benutzeroberfläche anzeigen, indem wir eine CustomersList-Komponente erstellen.

Schritt 7 – Daten von der API in der React-App anzeigen

In diesem Schritt erstellen wir die React-Komponente „CustomersList“. Eine React-Komponente repräsentiert einen Teil der Benutzeroberfläche. Sie ermöglicht es Ihnen außerdem, die Benutzeroberfläche in unabhängige, wiederverwendbare Elemente zu unterteilen.

Erstellen Sie zunächst die Datei CustomersList.js im Verzeichnis frontend/src:

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

Beginnen Sie mit dem Import von React und Component, um eine React-Komponente zu erstellen:

import React, { Component } from 'react';

Importieren und instanziieren Sie anschließend das im vorherigen Schritt erstellte CustomersService-Modul, das Methoden zur Kommunikation mit der Backend-REST-API bereitstellt:

...
import CustomersService from './CustomersService';
const customersService = new CustomersService();

Erstellen Sie als Nächstes eine CustomersList-Komponente, die von der Klasse Component erbt, um die REST-API aufzurufen. Eine React-Komponente muss die Klasse Component erweitern oder eine Unterklasse davon bilden. Weitere Informationen zu E6-Klassen und Vererbung finden Sie in unserem Tutorial zum Thema Klassen in JavaScript.

Fügen Sie den folgenden Code hinzu, um eine React-Komponente zu erstellen, die react.Component erweitert:

...
class CustomersList extends Component {

constructor(props) {
super(props);
this.state = {
customers: [],
nextPageURL: ''
};
this.nextPage = this.nextPage.bind(this);
this.handleDelete = this.handleDelete.bind(this);
}
}
export default CustomersList;

Im Konstruktor initialisieren wir das Zustandsobjekt. Dieses enthält die Zustandsvariablen unserer Komponente mithilfe eines leeren Arrays von Kunden. Dieses Array enthält die Kundendaten und die `nextPageURL`, die die URL der nächsten Seite enthält, die von der zugrunde liegenden API abgerufen wird. Wir binden außerdem die Methoden `nextPage()` und `handleDelete()` in dieses Objekt ein, sodass sie vom HTML-Code aus zugänglich sind.

Fügen Sie als Nächstes eine componentDidMount()-Methode und einen Aufruf von getCustomers() in der Klasse CustomersList vor der schließenden geschweiften Klammer hinzu.

Die Methode `componentDidMount()` ist eine Lebenszyklusmethode einer Komponente, die aufgerufen wird, wenn die Komponente erstellt und in das DOM eingefügt wird. `getCustomers()` ruft das Customer-Service-Objekt auf, um die erste Datenseite und den Link zur nächsten Seite vom Django-Backend abzurufen.

...
componentDidMount() {
var self = this;
customersService.getCustomers().then(function (result) {
self.setState({ customers: result.data, nextPageURL: result.nextlink})
});
}

Fügen Sie nun unterhalb von componentDidMount() die Methode handleDelete() hinzu, die die clientseitige Löschung übernimmt:

...
handleDelete(e,pk){
var self = this;
customersService.deleteCustomer({pk : pk}).then(()=>{
var newArr = self.state.customers.filter(function(obj) {
return obj.pk !== pk;
});
self.setState({customers: newArr})
});
}

Die Methode `handleDelete` ruft die Methode `deleteCustomer()` auf, um den Kunden anhand des Primärschlüssels (pk) zu löschen. Bei erfolgreicher Löschung wird das Kunden-Array nach dem gelöschten Kunden gefiltert.

Fügen Sie als Nächstes eine nextPage()-Methode hinzu, um die Daten für die nächste Seite abzurufen und den Link zur nächsten Seite zu aktualisieren:

...
nextPage(){
var self = this;
customersService.getCustomersByURL(this.state.nextPageURL).then((result) => {
self.setState({ customers: result.data, nextPageURL: result.nextlink})
});
}

Die Methode nextPage() ruft die Methode getCustomersByURL() auf, die die URL der nächsten Seite aus dem Zustandsobjekt this.state.nextPageURL abruft und das Kunden-Array mit den zurückgegebenen Daten aktualisiert.

Fügen Sie abschließend die render()-Methode der Komponente hinzu, die eine Tabelle mit Kunden aus dem Zustand der Komponente rendert:

...
render() {

return (
<div className="customers--list">
<table className="table">
<thead key="thead">
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
<th>Email</th>
<th>Address</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{this.state.customers.map( c =>
<tr key={c.pk}>
<td>{c.pk} </td>
<td>{c.first_name}</td>
<td>{c.last_name}</td>
<td>{c.phone}</td>
<td>{c.email}</td>
<td>{c.address}</td>
<td>{c.description}</td>
<td>
<button onClick={(e)=> this.handleDelete(e,c.pk) }> Delete</button>
<a href={"/customer/" + c.pk}> Update</a>
</td>
</tr>)}
</tbody>
</table>
<button className="btn btn-primary" onClick= { this.nextPage }>Next</button>
</div>
);
}

Hier ist der vollständige Inhalt der Datei:

import React, { Component } from 'react';
import CustomersService from './CustomersService';

const customersService = new CustomersService();

class CustomersList extends Component {

constructor(props) {
super(props);
this.state = {
customers: [],
nextPageURL: ''
};
this.nextPage = this.nextPage.bind(this);
this.handleDelete = this.handleDelete.bind(this);
}

componentDidMount() {
var self = this;
customersService.getCustomers().then(function (result) {
console.log(result);
self.setState({ customers: result.data, nextPageURL: result.nextlink})
});
}
handleDelete(e,pk){
var self = this;
customersService.deleteCustomer({pk : pk}).then(()=>{
var newArr = self.state.customers.filter(function(obj) {
return obj.pk !== pk;
});

self.setState({customers: newArr})
});
}

nextPage(){
var self = this;
console.log(this.state.nextPageURL);
customersService.getCustomersByURL(this.state.nextPageURL).then((result) => {
self.setState({ customers: result.data, nextPageURL: result.nextlink})
});
}
render() {

return (
<div className="customers--list">
<table className="table">
<thead key="thead">
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
<th>Email</th>
<th>Address</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{this.state.customers.map( c =>
<tr key={c.pk}>
<td>{c.pk} </td>
<td>{c.first_name}</td>
<td>{c.last_name}</td>
<td>{c.phone}</td>
<td>{c.email}</td>
<td>{c.address}</td>
<td>{c.description}</td>
<td>
<button onClick={(e)=> this.handleDelete(e,c.pk) }> Delete</button>
<a href={"/customer/" + c.pk}> Update</a>
</td>
</tr>)}
</tbody>
</table>
<button className="btn btn-primary" onClick= { this.nextPage }>Next</button>
</div>
);
}
}
export default CustomersList;

Nachdem wir nun die Komponente CustomersList zur Anzeige der Kundenliste erstellt haben, können wir eine Komponente hinzufügen, die das Anlegen und Aktualisieren von Kunden übernimmt.

Schritt 8 – React Create-Komponente hinzufügen und Client aktualisieren

In diesem Schritt erstellen wir die Komponente „CustomerCreateUpdate“, die das Anlegen und Aktualisieren von Kundendaten übernimmt. Dazu stellt sie ein Formular bereit, mit dem Benutzer neue Kundendaten eingeben oder bestehende Einträge aktualisieren können.

Erstellen Sie im Verzeichnis frontend/src eine Datei namens CustomerCreateUpdate.js:

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

Fügen Sie den folgenden Code hinzu, um eine React-Komponente zu erstellen, indem Sie React und Component importieren:

import React, { Component } from 'react';

Wir können auch die im vorherigen Schritt erstellte Klasse CustomersService importieren und instanziieren, die Methoden zur Kommunikation mit der Backend-REST-API bereitstellt:

...
import CustomersService from './CustomersService';

const customersService = new CustomersService();

Erstellen Sie als Nächstes eine CustomerCreateUpdate-Komponente, die von Component erbt, um Kunden zu erstellen und zu aktualisieren:

...
class CustomerCreateUpdate extends Component {

constructor(props) {
super(props);
}
}
export default CustomerCreateUpdate;

Fügen Sie in der Klassendefinition die render()-Methode der Komponente hinzu, die ein HTML-Formular rendert, das Kundeninformationen erfasst:

...
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>
);
}

Für jedes Formulareingabeelement fügt die Methode ein ref-Attribut hinzu, um auf den Wert des Formularelements zuzugreifen und ihn festzulegen.

Definieren Sie anschließend eine handleSubmit(event)-Methode oberhalb der render()-Methode, um das gewünschte Verhalten beim Klicken des Absenden-Buttons durch den Benutzer zu erzielen:

...
handleSubmit(event) {
const { match: { params } } = this.props;
if(params && params.pk){
this.handleUpdate(params.pk);
}
else
{
this.handleCreate();
}
event.preventDefault();
}
...

Die Methode `handleSubmit(event)` verarbeitet das Absenden des Formulars und ruft, abhängig von der Route, entweder die Methode `handleUpdate(pk)` auf, um den Client mit dem übergebenen Primärschlüssel zu aktualisieren, oder die Methode `handleCreate()`, um einen neuen Client zu erstellen. Wir werden diese Methoden in Kürze definieren.

Verknüpfen Sie im Komponentenkonstruktor die neu hinzugefügte Methode handleSubmit() mit this, damit Sie in Ihrem Formular darauf zugreifen können:

...
class CustomerCreateUpdate extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
...

Definieren Sie anschließend die Methode `handleCreate()`, um den Kunden aus den Formulardaten zu erstellen. Fügen Sie den folgenden Code oberhalb der Methode `handleSubmit(event)` ein:

...
handleCreate(){
customersService.createCustomer(
{
"first_name": this.refs.firstName.value,
"last_name": this.refs.lastName.value,
"email": this.refs.email.value,
"phone": this.refs.phone.value,
"address": this.refs.address.value,
"description": this.refs.description.value
}).then((result)=>{
alert("Customer created!");
}).catch(()=>{
alert('There was an error! Please re-check your form.');
});
}
...

Die Methode `handleCreate()` dient dazu, einen Kunden anhand der eingegebenen Daten anzulegen. Sie ruft die entsprechende Methode `CustomersService.createCustomer()` auf, welche wiederum die eigentliche API des Backends aufruft, um den Kunden zu erstellen.

Definieren Sie anschließend unterhalb der handleCreate-Methode die handleUpdate(pk)-Methode, um Aktualisierungen zu implementieren:

...
handleUpdate(pk){
customersService.updateCustomer(
{
"pk": pk,
"first_name": this.refs.firstName.value,
"last_name": this.refs.lastName.value,
"email": this.refs.email.value,
"phone": this.refs.phone.value,
"address": this.refs.address.value,
"description": this.refs.description.value
}
).then((result)=>{

alert("Customer updated!");
}).catch(()=>{
alert('There was an error! Please re-check your form.');
});
}

Die Methode updateCustomer() aktualisiert einen Kunden anhand neuer Informationen aus dem Kundeninformationsformular. Sie ruft die Methode customersService.updateCustomer() auf.

Fügen Sie anschließend eine `componentDidMount()`-Methode hinzu. Wenn der Benutzer die Route `customer/:pk` aufruft, soll das Formular mit den Kundeninformationen anhand des Primärschlüssels aus der URL befüllt werden. Dazu fügen wir die Methode `getCustomer(pk)` nach dem Mounten der Komponente im Lebenszyklusereignis `componentDidMount()` hinzu. Fügen Sie dazu den folgenden Code unterhalb des Komponentenkonstruktors ein:

...
componentDidMount(){
const { match: { params } } = this.props;
if(params && params.pk)
{
customersService.getCustomer(params.pk).then((c)=>{
this.refs.firstName.value = c.first_name;
this.refs.lastName.value = c.last_name;
this.refs.email.value = c.email;
this.refs.phone.value = c.phone;
this.refs.address.value = c.address;
this.refs.description.value = c.description;
})
}
}

Hier ist der vollständige Inhalt der Datei:

import React, { Component } from 'react';
import CustomersService from './CustomersService';
const customersService = new CustomersService();
class CustomerCreateUpdate extends Component {
constructor(props) {
super(props);

this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount(){
const { match: { params } } = this.props;
if(params && params.pk)
{
customersService.getCustomer(params.pk).then((c)=>{
this.refs.firstName.value = c.first_name;
this.refs.lastName.value = c.last_name;
this.refs.email.value = c.email;
this.refs.phone.value = c.phone;
this.refs.address.value = c.address;
this.refs.description.value = c.description;
})
}
}
handleCreate(){
customersService.createCustomer(
{
"first_name": this.refs.firstName.value,
"last_name": this.refs.lastName.value,
"email": this.refs.email.value,
"phone": this.refs.phone.value,
"address": this.refs.address.value,
"description": this.refs.description.value
} 
).then((result)=>{
alert("Customer created!");
}).catch(()=>{
alert('There was an error! Please re-check your form.');
});
}
handleUpdate(pk){
customersService.updateCustomer(
{
"pk": pk,
"first_name": this.refs.firstName.value,
"last_name": this.refs.lastName.value,
"email": this.refs.email.value,
"phone": this.refs.phone.value,
"address": this.refs.address.value,
"description": this.refs.description.value
} 
).then((result)=>{
console.log(result);
alert("Customer updated!");
}).catch(()=>{
alert('There was an error! Please re-check your form.');
});
}
handleSubmit(event) {
const { match: { params } } = this.props;
if(params && params.pk){
this.handleUpdate(params.pk);
}
else
{
this.handleCreate();
}
event.preventDefault();
}

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>
);
} 
}
export default CustomerCreateUpdate;

Durch die Erstellung der Komponente CustomerCreateUpdate können wir die Hauptkomponente der App aktualisieren, um Links zu den verschiedenen von uns erstellten Komponenten hinzuzufügen.

Schritt 9 – Aktualisieren Sie die Hauptanwendungskomponente

In diesem Abschnitt aktualisieren wir unsere App-Komponente, um eine Verbindung zu den Komponenten herzustellen, die wir in den vorherigen Schritten erstellt haben.

Führen Sie im Frontend-Ordner den folgenden Befehl aus, um den React Router zu installieren, mit dem Sie Routing und Navigation zwischen verschiedenen React-Komponenten hinzufügen können:

cd ~/djangoreactproject/frontend
npm install --save react-router-dom

Öffnen Sie als Nächstes ~/djangoreactproject/frontend/src/App.js:

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

Löschen Sie alle vorhandenen Elemente und fügen Sie den folgenden Code hinzu, um die notwendigen Klassen für das Routing zu importieren. Dies sind BrowserRouter, das eine Router-Komponente erstellt, und Route, das eine Route-Komponente erstellt:

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 hält die Benutzeroberfläche mithilfe der HTML5 History API mit der URL synchron.

Erstellen Sie als Nächstes ein Basislayout, das die Basiskomponente bereitstellt, die von der BrowserRouter-Komponente umschlossen werden soll:

...
const BaseLayout = () => (
<div className="container-fluid">
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<a className="navbar-brand" href="#">Django React Demo</a>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNavAltMarkup">
<div className="navbar-nav">
<a className="nav-item nav-link" href="/">CUSTOMERS</a>
<a className="nav-item nav-link" href="/customer">CREATE CUSTOMER</a>
</div>
</div>
</nav>
<div className="content">
<Route path="/" exact component={CustomersList} />
<Route path="/customer/:pk" component={CustomerCreateUpdate} />
<Route path="/customer/" exact component={CustomerCreateUpdate} />
</div>
</div>
)

Wir verwenden die Route-Komponente, um die Routen unserer Anwendung zu definieren. Die Komponente, die der Router laden soll, sobald eine Übereinstimmung gefunden wird, ist diejenige, die benötigt wird. Jede Route benötigt eine Route, die die zu vergleichende Route angibt, und eine Komponente, die die zu vergleichende Komponente angibt. Das Attribut „exact“ weist den Router an, die Route exakt zuzuordnen.

Erstellen Sie abschließend die App-Komponente, die Haupt- oder oberste Komponente unserer React-Anwendung:

...
class App extends Component {
render() {
return (
<BrowserRouter>
<BaseLayout/>
</BrowserRouter>
);
}
}
export default App;

Wir haben die BaseLayout-Komponente mit der BrowserRouter-Komponente umschlossen, da unsere Anwendung im Browser ausgeführt werden soll.

Die fertige Datei sieht folgendermaßen aus:

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';
const BaseLayout = () => (
<div className="container-fluid">
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<a className="navbar-brand" href="#">Django React Demo</a>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNavAltMarkup">
<div className="navbar-nav">
<a className="nav-item nav-link" href="/">CUSTOMERS</a>
<a className="nav-item nav-link" href="/customer">CREATE CUSTOMER</a>

</div>
</div>
</nav>
<div className="content">
<Route path="/" exact component={CustomersList} />
<Route path="/customer/:pk" component={CustomerCreateUpdate} />
<Route path="/customer/" exact component={CustomerCreateUpdate} />
</div>
</div>
)
class App extends Component {
render() {
return (
<BrowserRouter>
<BaseLayout/>
</BrowserRouter>
);
}
}
export default App;

Nachdem wir unserer Anwendung das Routing hinzugefügt haben, können wir sie nun testen. Rufen Sie http://localhost:3000 auf. Sie sollten die Startseite der Anwendung sehen:

Mit diesem Programm haben Sie nun die Grundlage für ein CRM-Programm geschaffen.

Ergebnis

In diesem Tutorial haben Sie eine Demo-Anwendung mit Django und React erstellt. Sie haben das Django REST Framework zum Erstellen der REST-API, Axios zum Aufrufen der API und Bootstrap 4 für das CSS-Styling verwendet. Den Quellcode für dieses Projekt finden Sie in diesem GitHub-Repository.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Das könnte Ihnen auch gefallen

VPN-Auto-Disconnect-Software

Was ist eine VPN-Auto-Disconnect-Software? Eine VPN-Auto-Disconnect-Software ist eine fortschrittliche Sicherheitsmaßnahme, die…