Consume Js Form Ver
Consume Js Form Ver
https://www.makeuseof.com/consume-django-apis-with-django-templates/
When using a backend technology or framework like Django, Laravel, or Node.js to write REST
APIs, you need to have an additional frontend skill using frameworks like React, Angular, and Vue
to consume the API endpoints. But that's not always the case, you can consume the APIs in Django
itself using Django templates.
https://www.makeuseof.com/consume-django-apis-with-
django-templates/
https://github.com/makeuseofcode/Payment-Wallet-Using-Django-/blob/main/
payment_wallet_project/wallet/views.py
For this tutorial, you will build APIs for a payment wallet.
The full source code is available in a GitHub repository .
Start by creating a virtual environment. In this case, you will use the Pipenv library.
pipenv install django djangorestframework
This command installs the necessary libraries as well as creates a virtual environment.
Activate the virtual environment using the command below:
pipenv shell
Using the full stop (.) at the end of the django-admin command ensures the project avoids creating
a duplicate directory of the project directory.
Create a new Django app within the project directory.
python manage.py startapp wallet
Now, proceed to build your API application using the steps below.
In the wallet directory, create a new file serializers.py, and write the wallet and transaction model
serializers.
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__'
The serializers consider all the fields in the wallet and transaction models.
In wallet/views.py, write the views for handling the logic of implementing the wallet functionality.
This includes the deposit and withdrawal abilities.
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
Next, define the URL routing for the API by creating a wallet/urls.py file:
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'),
]
In the PayApp/settings.py file, add the wallet and rest_framwork apps to the
INSTALLED_APPS list.
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
]
This will register the wallet and rest_framework apps to the Django project application.
Object 2
The HTML file renders the deposit and withdrawal APIs in a beautiful user interface designed using
Bootstrap.
User Interaction With Forms
In the HTML file, create a script tag and add the following code to the deposit form submission
event listener.
<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>
Next, add the event listener for the withdrawal form submission using the code below:
<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>
The event listener is responsible for handling the deposit and withdrawal (#deposit-form and
#withdraw-form) form submissions.
The URL for the fetch request is for matching the URLs for deposit and withdrawal actions.
The JSON responses for the deposits and withdrawals are then parsed to get the updated balance
(data.balance). They are then formatted and displayed on the page.
Next, in the wallet/views.py, add the following update to render the wallet.html page:
Object 3
In this example, you will use the first() query method to select a single user’s wallet for
demonstration purposes.
Update the urls.py file by adding a path to the wallet_view as follows:
from .views import wallet_view
urlpatterns = [
...
path('home/', wallet_view, name='wallet-page'),
]
Object 5