Gebruik Django API's op een eenvoudige manier met Django Templates
Wanneer je een backend technologie of framework zoals Django, Laravel of Node.js gebruikt om REST API’s te schrijven, heb je een extra frontend vaardigheid nodig met frameworks zoals React, Angular en Vue om de API endpoints te consumeren. Maar dat is niet altijd het geval, u kunt de API’s in Django zelf consumeren met behulp van Django-templates.
Een Django-project en API-eindpunten opzetten
Om het proces te starten, zullen we beginnen met het aanmaken van een projectmap in ons bestandssysteem. Navigeer met behulp van de Terminal-toepassing naar de gewenste locatie en maak een nieuwe map aan die zal dienen als organisatorische hub voor uw onderneming.
mkdir payment_wallet_project
cd payment_wallet_project
Om deze instructiegids te kunnen volgen, ga je API’s (Application Programming Interfaces) bouwen die bedoeld zijn voor gebruik in combinatie met een digitale portemonnee die wordt gebruikt voor financiële transacties.
De volledige broncode is toegankelijk via een GitHub repository, die direct beschikbaar is voor referentie en verder onderzoek.
Maak om te beginnen een virtuele omgeving met de Pipenv bibliotheek als basis voor de ontwikkelingscontext van ons project.
pipenv install django djangorestframework
Het uitvoeren van deze instructie resulteert in de installatie van de vereiste bibliotheken en het opzetten van een virtuele omgeving.
Om een virtuele omgeving te activeren, voer je het volgende commando uit in je terminal of command prompt:bashsource /venv/bin/activateVervang
door het werkelijke pad naar je projectmap op je computer. Hierdoor wordt de virtuele omgeving geactiveerd en kun je de pakketten die erin zijn geïnstalleerd gebruiken voor je Python-script.
pipenv shell
Om een nieuw Django-project aan te maken, navigeert u naar de gewenste map en voert u het commando “django-admin startproject PayApp” uit. Hierdoor wordt een nieuw project met de naam “PayApp” op de opgegeven locatie aangemaakt.
django-admin startproject PayApp .
Het gebruik van het afsluitende leesteken (. https://en.wikipedia.org/wiki/. ) na de opdracht “django-admin” minimaliseert de kans op een dubbele replicatie van de primaire mappenstructuur van het project binnen de nieuw gemaakte Django-applicatie.
Voer de volgende stappen uit om een nieuwe Django-applicatie in de bestaande projectmap te maken:1. Open uw terminal en navigeer naar de hoofdmap van uw Django-project met behulp van de opdracht cd
.2. Zodra u in de juiste map bent, voert u de volgende opdracht uit om een nieuwe Django app genaamd “myapp” te maken:bashpython manage.py startapp myapp3.Dit genereert een nieuwe map met de naam “myapp” in de map “apps” van uw Django-project. In deze map vindt u verschillende bestanden die de basisstructuur van uw nieuwe app vormen.
python manage.py startapp wallet
Om te beginnen met de bouw van uw API-applicatie, volgt u de richtlijnen
Creating a Payment Wallet REST API
Om een uitgebreide backend voor uw cryptocurrency-applicatie te implementeren, is het essentieel om het bestand wallet/models.py
in uw Django-project te openen en twee aparte modellen voor de portemonnee en transacties te maken. Deze modellen dienen als basis voor uw databaseschema en bieden de noodzakelijke structuur voor het opslaan en ophalen van gegevens met betrekking tot gebruikersaccounts en transacties binnen het systeem.
from django.db import models
class Wallet(models.Model):
user = models.CharField(max_length=100)
balance = models.DecimalField(max_digits=10, decimal_places=2)
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user
class Transaction(models.Model):
wallet = models.ForeignKey(Wallet, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=10, decimal_places=2)
timestamp = models.DateTimeField(auto_now_add=True)
Om een nieuw bestand aan te maken in de portemonnee map, getiteld “serializers.py”, gaan we verder met het genereren van een set serializers voor zowel de portemonnee- als transactiemodellen. Dit zal effectief gegevensbeheer en -organisatie binnen het backendsysteem van onze applicatie vergemakkelijken.
from rest_framework import serializers
from .models import Wallet, Transaction
class WalletSerializer(serializers.ModelSerializer):
class Meta:
model = Wallet
fields = '__all__'
class TransactionSerializer(serializers.ModelSerializer):
class Meta:
model = Transaction
fields = '__all__'
De serializers houden rekening met elk attribuut dat aanwezig is in de schema’s van zowel het portemonnee- als het transactiemodel.
In het bestand wallet/views.py
definiëren we de benodigde view-functies om de stortings- en opnamefuncties van de portemonnee af te handelen. Deze functies zijn verantwoordelijk voor het verwerken van gebruikersverzoeken en het bijwerken van de relevante gegevens in de database. Door deze views te implementeren, kunnen we de portemonnee-functie effectief implementeren in onze applicatie.
from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework.decorators import action
from decimal import Decimal
from .models import Wallet, Transaction
from .serializers import WalletSerializer, TransactionSerializer
class WalletViewSet(viewsets.ModelViewSet):
queryset = Wallet.objects.all()
serializer_class = WalletSerializer
@action(detail=True, methods=['post'])
def deposit(self, request, pk=None):
wallet = self.get_object()
amount = Decimal(request.data['amount'])
wallet.balance \\+= amount
wallet.save()
serializer = WalletSerializer(wallet)
return Response(serializer.data)
@action(detail=True, methods=['post'])
def withdraw(self, request, pk=None):
wallet = self.get_object()
amount = Decimal(request.data['amount'])
if wallet.balance < amount:
return Response({'error': 'Insufficient funds'},
status=status.HTTP_400_BAD_REQUEST)
wallet.balance -= amount
wallet.save()
serializer = WalletSerializer(wallet)
return Response(serializer.data)'
class TransactionViewSet(viewsets.ModelViewSet):
queryset = Transaction.objects.all()
Serializer_class = TransactionSerializer
Om de programmeerinterface van de webtoepassing (API) op te zetten en te specificeren hoe elk eindpunt moet worden benaderd, maken we een nieuw Python-bestand met de naam “wallet/urls.py” in onze projectmapstructuur. Dit bestand dient als een essentieel onderdeel van de algehele architectuur en maakt naadloze communicatie mogelijk tussen de front-end componenten en back-end diensten.
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import WalletViewSet, TransactionViewSet, wallet_view
router = DefaultRouter()
router.register(r'wallets', WalletViewSet, basename='wallets')
router.register(r'transactions', TransactionViewSet, basename='transactions')
urlpatterns = [
path('api/', include(router.urls)),
path('wallets/<int:pk>/deposit/', WalletViewSet.as_view({'post': 'deposit'}),
name='wallet-deposit'),
path('wallets/<int:pk>/withdraw/', WalletViewSet.as_view({'post': 'withdraw'}),
name='wallet-withdraw'),
]
Neem de URL-patronen van je applicatie op in het bestandurls.py van je project, inclusief die voor de gespecificeerde app.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('wallet.urls')),
]
Om de functionaliteit van een digitale portemonnee in uw applicatie op te nemen, is het noodzakelijk om zowel de “wallet” als de “rest\_framework” bibliotheken op te nemen in de “INSTALLED\_APPS” lijst in het “PayApp/settings.py” bestand. Dit zorgt ervoor dat deze applicaties correct worden geïnstalleerd en geïntegreerd in het systeem.
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework", # new
"wallet", # new
]
Het registreren van de portemonnee en rest\_framework applicaties aan het Django project’s applicatie register is een proces dat het mogelijk maakt deze modules te gebruiken binnen de bredere context van het project, het verbeteren van hun functionaliteit door gebruik te maken van de middelen die door het Django framework.
De API gebruiken met Django Templates
Om een gebruiksvriendelijke interface te ontwikkelen voor interactie met onze backend API met behulp van Django templates, moeten we een nieuw template aanmaken in de map “wallet” in de map “templates”. De specifieke sjabloon die we nodig hebben heet “wallet.html” en moet de volgende HTML-code bevatten die hieronder staat.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Wallet</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/
css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>Wallets</h1>
<table class="table">
<thead>
<tr>
<th>User</th>
<th>Balance</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ wallet.user }}</td>
<td id="balance">{{ wallet.balance }}</td>
<td>
<div id="loading-indicator" class="d-none">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
<p>Please wait while the deposit is being processed.</p>
</div>
<form id="deposit-form" method="post">
{% csrf_token %}
<input type="number" name="amount" step="0.01" min="0" required>
<button type="submit" class="btn btn-success">Deposit</button>
</form>
<form method="post" id="withdraw-form">
{% csrf_token %}
<input type="number" name="amount" step="0.01" min="0" required>
<button type="submit" class="btn btn-danger">Withdraw</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Het HTML-document presenteert op effectieve wijze de programmeerinterfaces voor stortingen en opnames binnen een esthetisch aantrekkelijke grafische gebruikersinterface, waarbij gebruik wordt gemaakt van het visueel aantrekkelijke Bootstrap-raamwerk voor ontwerpdoeleinden.
Gebruikersinteractie met formulieren
Neem in het HTML-document een scriptelement op en integreer dit in de event handler van de indieningsgebeurtenis van het stortingsformulier.
<script>
document.querySelector('#deposit-form').addEventListener('submit', function (event) {
event.preventDefault();
document.querySelector('#loading-indicator').classList.remove('d-none');
const amount = parseFloat(document.querySelector("#deposit-form " \\+
"input[name='amount']").value);
fetch("{% url 'wallet-deposit' wallet.id %}", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": getCookie("csrftoken")
},
body: JSON.stringify({ amount: amount })
})
.then(response => response.json())
.then(data => {
console.log(data);
if (data.balance !== undefined) {
// Convert to number and format
const newBalance = parseFloat(data.balance).toFixed(2);
document.querySelector("#balance").textContent = newBalance;
document.querySelector('#loading-indicator').classList.
add('d-none');
}
})
.catch(error => {
console.error("Error:", error);
document.querySelector('#loading-indicator')
.classList.add('d-none');
});
});
</script>
Integreer vervolgens de event listener voor de verzending van het opnameformulier door de meegeleverde code als volgt te gebruiken:
<script>
document.querySelector('#withdraw-form').addEventListener('submit', function (event) {
event.preventDefault();
document.querySelector('#loading-indicator').classList.remove('d-none');
const amount = parseFloat(document.querySelector("#withdraw-form " \\+
"input[name='amount']").value);
fetch("{% url 'wallet-withdraw' wallet.id %}", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": getCookie("csrftoken")
},
body: JSON.stringify({ amount: amount })
})
.then(response => response.json())
.then(data => {
console.log(data);
if (data.balance !== undefined) { // Change to 'balance' for withdrawal
const newBalance = parseFloat(data.balance).toFixed(2);
document.querySelector("#balance").textContent = newBalance;
document.querySelector('#loading-indicator').classList.add('d-none');
}
})
.catch(error => {
console.error("Error:", error);
document.querySelector('#loading-indicator').classList.add('d-none');
});
});
</script>
De event listener is verantwoordelijk voor het beheer van de verzending van de stortings- en opnameformulieren, die zijn gekoppeld aan respectievelijk de elementen “#deposit-form” en “#withdraw-form”.
De URL van het ophaalverzoek komt overeen met de URL’s van de stortings- en opnameacties.
Het proces omvat het parsen van de JSON-responses van zowel stortings- als opnametransacties om het huidige rekeningsaldo op te halen, dat vervolgens wordt opgehaald via de eigenschap data.balance
. Vervolgens worden deze waarden getransformeerd en gepresenteerd op de webpagina.
Om de inhoud van de digitale portemonnee van een gebruiker op de webapplicatie weer te geven, is het noodzakelijk om het bestand wallet/views.py
aan te passen door een bijgewerkte versie van de functie render()
op te nemen die de sjabloon wallet.html
weergeeft. Deze functie moet rekening houden met alle wijzigingen die zijn aangebracht in het model van de portemonnee en ervoor zorgen dat de weergegeven informatie de huidige status van de portemonnee van de gebruiker nauwkeurig weergeeft.
from django.shortcuts import render
def wallet_view(request):
# Retrieve the wallet to display
wallet = Wallet.objects.first()
return render(request, 'wallet.html', {'wallet': wallet})
In dit illustratieve voorbeeld zullen we de utilitaire functionaliteit van de methode first()
gebruiken om de virtuele portefeuille van een enkele gebruiker te selecteren om de werking ervan te demonstreren.
Gelieve het bestand urls.py
in uw project bij te werken door een URL-route op te nemen voor de wallet_view
, met vermelding van het juiste pad zoals hieronder getoond:
from .views import wallet_view
urlpatterns = [
...
path('home/', wallet_view, name='wallet-page'),
]
" http://127.0.0.1:8000/home/ “.
Om te controleren of alle wijzigingen met succes zijn toegepast op de database, wordt aanbevolen een aantal stappen uit te voeren. Zorg er ten eerste voor dat de benodigde afhankelijkheden zijn geïnstalleerd door het commando “makemigrations” in de terminal of opdrachtprompt uit te voeren. Hiermee worden migratiebestanden gegenereerd op basis van wijzigingen die zijn aangebracht in de modellen binnen het project. Pas vervolgens deze migraties toe met het commando “migrate”. Zodra beide processen zonder fouten zijn voltooid, geeft dit aan dat de wijzigingen correct zijn doorgevoerd. Start tot slot de Django-applicatie met de opdracht “python manage.py runserver” in de terminal of opdrachtprompt. De server zou nu klaar moeten zijn voor gebruik, zodat u toegang kunt krijgen tot de website of dienst via een webbrowser.
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
Om toegang te krijgen tot de eindpuntbestemmingen van onze application programming interface, verzoeken we je om je webbrowser naar de URL http://127.0.0.1:8000/api/ te sturen.
Verwachte uitvoer:
Navigeer naar de localhost voor interactie met de portemonnee.
Verwachte uitvoer:
De digitale portemonnee van de gebruiker geeft het saldo van zijn huidige rekening weer en biedt hem een handige manier om naar behoefte stortingen en opnames te doen.
Django sjablonen begrijpen en hun rol in API consumptie
Hoewel Django sjablonen uitblinken in het tonen van stationaire gegevens, zijn ze onderhevig aan beperkingen als het gaat om integratie met Application Programming Interfaces (API’s).
Django’s templatingsysteem biedt een beperkter niveau van aanpasbaarheid in vergelijking met andere alternatieven zoals Jinja2 of Twig. Dit komt door de afhankelijkheid van vooraf gedefinieerde renderstrategieën die handmatige manipulatie noodzakelijk maken bij het werken met complexe datastructuren die zijn verkregen van API’s die JSON-geformatteerde informatie leveren.
Django, een veelgebruikt hedendaags webframework, biedt inherent geen native ondersteuning voor het afhandelen van asynchrone verzoeken binnen zijn templingsysteem. Ondanks deze beperking hebben andere moderne frameworks zoals Flask het gebruik van async/await syntaxis omarmd in hun ontwikkelproces.Als gevolg hiervan is het bij het gebruik van Django’s template engine noodzakelijk om alle verzoeken opeenvolgend te voltooien voordat een webpagina wordt gerenderd, zelfs als er meerdere gegevensbronnen nodig zijn voor het genereren van inhoud.
Django templates hebben geen natuurlijk mechanisme om fouten op te vangen die kunnen ontstaan door API-gebruik. Het is niet ongewoon dat uitzonderingen worden gegooid tijdens dergelijke operaties, waardoor handmatige interventie nodig is om ze af te handelen binnen de grenzen van het sjabloon. Dit kan leiden tot omslachtige en moeilijk te onderhouden code.
Schaalbare applicaties bouwen
Django templates faciliteren de scheiding tussen presentatielagen en bedrijfslogica, waardoor ontwikkelaars zich kunnen concentreren op het samenstellen van herbruikbare en duurzame code. Desondanks zijn Django templates, gezien hun beperkingen, mogelijk niet optimaal voor het omgaan met API’s op grote schaal. In dergelijke situaties blijven clientframeworks zoals React relevant voor het bouwen van schaalbare softwaresystemen.