Contents

透過 Django 模板輕鬆使用 Django API

當使用 Django、Laravel 或 Node.js 等後端技術或框架來編寫 REST API 時,您需要具備使用 React、Angular 和 Vue 等框架來使用 API 端點的額外前端技能。但情況並非總是如此,您可以使用 Django 範本使用 Django 本身中的 API。

設定 Django 專案和 API 端點

啟動該過程,我們將首先在檔案系統中建立一個專案資料夾。使用終端應用程序,請導航到所需位置並產生一個新目錄作為您的工作的組織中心。

 mkdir payment_wallet_project
cd payment_wallet_project 

為了遵循本指導指南,您將建立旨在與用於金融交易的數位錢包結合使用的應用程式介面 (API)。

完整的源代碼可以透過 GitHub 存儲庫訪問,該存儲庫可以隨時供參考和進一步探索。

首先,利用 Pipenv 函式庫建立一個虛擬環境作為我們專案開發環境的基礎。

 pipenv install django djangorestframework 

執行該指令將導致所需庫的安裝和虛擬環境的建立。

若要啟動虛擬環境,請在終端機或命令提示字元中執行下列命令:bashsource/venv/bin/activate請將``替換為電腦上專案目錄的實際路徑。這將啟動虛擬環境並允許您將其中安裝的任何套件用於 Python 腳本。

 pipenv shell

若要建立新的 Django 項目,請導航至您的首選目錄並執行指令「django-admin startproject PayApp」。這將在指定位置啟動一個名為“PayApp”的新專案的創建。

 django-admin startproject PayApp . 

在「django-admin」指令之後使用結束標點符號(. https://en.wikipedia.org/wiki/. )可以最大限度地減少新建立的Django 應用程式中專案主資料夾結構的重複副本。

若要在現有專案目錄中建立新的 Django 應用程序,請執行以下步驟:1.打開終端並使用“cd”命令導航到 Django 專案的根資料夾。2.進入正確的目錄後,執行以下命令以建立名為「myapp」的新 Django 應用程式:bashpython manage.py startapp myapp3。這將在 Django 專案的「apps」目錄中產生一個名為「myapp」的新目錄。在此目錄中,您將找到構成新應用程式基本結構的幾個檔案。

 python manage.py startapp wallet 

要開始建立您的 API 應用程序,請遵循概述的指南

建立支付錢包 REST API

為了為您的加密貨幣應用程式實現全面的後端,必須在 Django 專案中開啟「wallet/models.py」文件,並為錢包和交易創建兩個單獨的模型。這些模型將作為資料庫模式的基礎,並提供用於儲存和檢索與系統內使用者帳戶和交易相關的資料所需的結構。

 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) 

為了在錢包目錄中建立一個名為「serializers.py」的新文件,我們將繼續為錢包和交易模型產生一組序列化器。這將有助於我們應用程式後端系統內的有效資料管理和組織。

 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__'

序列化器考慮錢包和交易模型模式中存在的每個屬性。

在「wallet/views.py」檔案中,我們將定義必要的視圖函數來處理錢包的存款和提款功能。這些函數將負責處理使用者請求並相應更新資料庫中的相關資料。透過實現這些視圖,我們可以在應用程式中有效地實現錢包功能。

 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

為了建立 Web 應用程式介面 (API) 並指定如何存取每個端點,我們將在專案目錄結構中建立一個名為「wallet/urls.py」的新 Python 檔案。該文件作為整體架構的重要組成部分,實現前端元件和後端服務之間的無縫通訊。

 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'),

] 

將應用程式的 URL 模式合併到專案的 urls.py 檔案中,包括指定應用程式的 URL 模式。

 from django.contrib import admin
from django.urls import path, include

urlpatterns = [
   path('admin/', admin.site.urls),
   path('', include('wallet.urls')),
] 

為了將數位錢包的功能合併到您的應用程式中,有必要將「wallet」和「rest\_framework」庫包含在「PayApp/settings.py」中的「INSTALLED\_APPS」清單中「 檔案。這將確保這些應用程式正確安裝並與整個系統整合。

 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

] 

將錢包和rest\_framework應用程式註冊到Django專案的應用程式註冊表是一個使這些模組能夠在專案的更廣泛上下文中使用的過程,透過利用Django框架提供的資源來增強它們的功能。

透過 Django 範本使用 API

為了開發一個用戶友好的介面來使用 Django 模板與後端 API 交互,我們需要在「templates」目錄中的「wallet」資料夾中建立一個新模板。所需的特定模板名為“wallet.html”,它應包含下面提供的後續 HTML 程式碼。

 <!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> 

HTML 文件在美觀的圖形使用者介面中有效地呈現了存款和提款應用程式程式設計介面,並利用視覺上吸引人的 Bootstrap 框架進行設計。

使用者與表單的交互

在 HTML 文件中,合併一個腳本元素並將其整合到與存款表單提交事件關聯的事件處理程序中。

 <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> 

隨後,使用提供的程式碼合併用於提交提款表單的事件偵聽器,如下所示:

 <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> 

事件監聽器負責管理存款和提款表單的提交,這些表單分別與「#deposit-form」和「#withdraw-form」元素相關聯。

提取請求的 URL 對應於與存款和提款操作關聯的 URL。

該過程涉及解析存款和提款交易的 JSON 回應,以檢索當前帳戶餘額,隨後透過 data.balance 屬性檢索該餘額。隨後,這些值被轉換並呈現在網頁上。

為了在 Web 應用程式上顯示使用者數位錢包的內容,需要透過合併渲染 wallet.html 的更新版本的 render() 函數來修改 wallet/views.py 檔案。` 模板。此功能應考慮對「錢包」模型所做的任何更改,並確保顯示的資訊準確反映用戶錢包的當前狀態。

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

在這個範例中,我們將使用「first()」方法的實用功能來選擇單一使用者的虛擬投資組合,以示範其操作。

請透過合併「wallet_view」的 URL 路由來更新專案中的「urls.py」文件,指定適當的路徑,如下所示:

 from .views import wallet_view

urlpatterns = [
   ...
     path('home/', wallet_view, name='wallet-page'),
]

http://127.0.0.1:8000/home/」。

為了驗證所有變更是否已成功應用到資料庫,建議執行一系列步驟。首先,確保透過在終端機或命令提示字元中執行“makemigrations”命令安裝必要的依賴項。這將根據專案內模型所做的任何修改來產生遷移檔案。接下來,使用「migrate」指令套用這些遷移。一旦兩個過程均順利完成,則表示變更已正確實施。最後,在終端機或命令提示字元中使用「python manage.py runserver」命令啟動 Django 應用程式。伺服器現在應該可以使用了,您可以透過網頁瀏覽器存取網站或服務。

 python manage.py makemigrations
python manage.py migrate

python manage.py runserver

若要存取我們的應用程式介面的端點目標,請將您的Web 瀏覽器定向至URL http://127.0.0.1:8000/api/

預期輸出:

/bc/images/consume-django-apis-the-easy-way-with-django-templates-featured-image-wallet-api.jpeg

導覽至 localhost 與錢包互動。

預期輸出:

/bc/images/consume-django-apis-the-easy-way-with-django-templates-featured-image-wallet.jpeg

用戶的數位錢包顯示他們的經常帳戶餘額,為他們提供根據需要啟動存款和提款的便捷方式。

了解 Django 範本及其在 API 使用中的作用

儘管 Django 模板擅長展示固定數據,但在與應用程式介面 (API) 整合時它們受到限制。

與 Jinja2 或 Twig 等其他替代方案相比,Django 的模板系統提供了更有限的適應性。這是因為它依賴預先定義的渲染策略,在處理從提供 JSON 格式資訊的 API 取得的複雜資料結構時,需要手動操作。

Django 是一種廣泛使用的當代 Web 框架,它本身並不提供在其模板系統內處理非同步請求的本機支援。儘管有這種限制,其他現代框架(例如 Flask)已經在其開發過程中使用了 async/await 語法。因此,在使用 Django 的模板引擎時,即使需要多個資料來源來產生內容,也必須在渲染網頁之前順序完成所有請求。

Django 範本缺乏自然的機制來適應 API 使用中可能出現的錯誤。在此類操作期間引發異常的情況並不罕見,需要手動幹預才能在模板的範圍內處理它們。這可能會導致程式碼繁瑣且難以維護。

建立可擴展的應用程式

Django 模板有助於將表示層與業務邏輯分離,使開發人員能夠專注於編寫可重複使用且可持續的程式碼。然而,考慮到它們的限制,Django 範本可能不是處理大規模 API 的最佳選擇。在這種情況下,像 React 這樣的客戶端框架仍然與建立可擴展的軟體系統相關。