目錄
它有什麼作用?
安裝方法
簡介
首頁 後端開發 Python教學 Python和JavaScript間交換資料的方法

Python和JavaScript間交換資料的方法

May 11, 2023 pm 11:04 PM
javascript python

telepath是一個Django庫,用於在Python和JavaScript之間交換數據,使您可以建立具有豐富客戶端介面的應用程序,同時將業務邏輯保留在伺服器端程式碼中。

它有什麼作用?

它提供了一個將包括Python物件在內的結構化資料打包為JSON可序列化格式的機制。透過向對應的JavaScript實作註冊該機制,可以擴展該機制以支援任何Python類別。然後,打包的資料可以包含在HTTP回應中,並在JavaScript中解壓縮以獲得與原始資料等效的資料結構。

安裝方法

pip install telepath
登入後複製
登入後複製

並將'telepath'新增至專案的INSTALLED_APPS。

簡介

假設我們正在建立一個用於玩跳棋的Django應用程式。我們已經花了數天或數週的時間,建構了遊戲規則的Python實現,並提供了代表當前遊戲狀態和各個部分的類別。但是,我們也希望為播放器提供一個適當且友善的使用者介面,這意味著該是我們編寫JavaScript前端的時候了。我們的UI程式碼不可避免地將擁有自己的對象,這些對象代表不同的角色,鏡像我們正在伺服器上追蹤的資料結構——但我們無法發送Python對象,因此將這些資料傳送到客戶端通常將意味著設計遊戲狀態的JSON表示形式,並在兩端分別設計大量樣式程式碼,遍歷資料結構以在本機物件之間來回轉換。讓我們看看telepath如何簡化這個過程。

一個完整的跳棋遊戲對於本教學來說有點太多了,所以我們只選擇渲染這一步...

在Python環境中,創建一個新的Django專案:

pip install "Django>=3.1,<3.2" django-admin startproject draughts cd draughts ./manage.py startapp games
登入後複製

在draughts / settings.py的INSTALLED_APPS清單中加入'games'。

為簡單起見,在本範例中,我們將不涉及資料庫,而是將遊戲狀態表示為普通的Python類別而不是Django模型。修改games/views.py,如下所示:

from django.shortcuts import render   class Piece:     def __init__(self, color, position):         self.color = color         self.position = position   class GameState:     def __init__(self, pieces):         self.pieces = pieces      @staticmethod     def new_game():         black_pieces = [             Piece(&#39;black&#39;, (x, y))             for y in range(0, 3)             for x in range((y + 1) % 2, 8, 2)         ]         white_pieces = [             Piece(&#39;white&#39;, (x, y))             for y in range(5, 8)             for x in range((y + 1) % 2, 8, 2)         ]         return GameState(black_pieces + white_pieces)   def game(request):     game_state = GameState.new_game()      return render(request, &#39;game.html&#39;, {})
登入後複製

如下所示建立games/templates/game.html:

<!doctype html> <html>     <head>         <title>Draughts</title>         <script>             document.addEventListener('DOMContentLoaded', event => {                 const gameElement = document.getElementById('game');                 gameElement.innerHTML = 'TODO: render the board here'             });         </script>     </head>     <body>         <h2>Draughts</h2>         <div id="game">         </div>     </body> </html>
登入後複製

將新視圖新增至draughts/urls.py:

from django.contrib import admin from django.urls import path  from games.views import game  urlpatterns = [     path('', game),     path('admin/', admin.site.urls), ]
登入後複製

現在,使用./manage.py runserver啟動伺服器,並造訪http:// localhost:8000 /。

到目前為止,我們已經創建了一個代表新遊戲的GameState物件——現在是時候引入telepath,以便我們可以將該物件傳輸到客戶端。執行下方指令:

pip install telepath
登入後複製
登入後複製

並將'telepath'加入draughts /  settings.py中的INSTALLED_APPS清單中。現在編輯games/views.py檔案:

import json from django.shortcuts import render from telepath import JSContext  # ...  def game(request):     game_state = GameState.new_game()      js_context = JSContext()     packed_game_state = js_context.pack(game_state)     game_state_json = json.dumps(packed_game_state)      return render(request, 'game.html', {         'game_state_json': game_state_json,     })
登入後複製

這裡JSContext是一個幫助工具,用於管理遊戲狀態物件到我們可以在Javascript中使用的表示形式的轉換。 js_context.pack接受該物件並將其轉換為可以JSON序列化並傳遞到我們的模板的值。但是,現在重新載入頁面失敗,並出現以下形式的錯誤:don't  know how to pack object:

這是因為GameState是Telepath尚不知道如何處理的自訂Python類型。傳遞給pack的任何自訂類型必須連結到對應的JavaScript實作;這是透過定義Adapter物件並將其註冊到telepath來完成的。如下更新game  / views.py:

import json from django.shortcuts import render from telepath import Adapter, JSContext, register  # ...  class GameState:     # keep definition as before   class GameStateAdapter(Adapter):     js_constructor = 'draughts.GameState'      def js_args(self, game_state):         return [game_state.pieces]      class Media:         js = ['draughts.js']   register(GameStateAdapter(), GameState)
登入後複製

此處js_constructor是JavaScript建構子的標識符,該標識符將用於在客戶端上建立GameState實例,並且js_args定義了將傳遞給此構造函數的參數列表,以重新建立給定game_state物件的JavaScript對應物件 。 Media類別指示文件,該文件遵循Django對格式媒體的約定,可在其中找到GameState的JavaScript實作。稍後我們將看到此JavaScript實作的外觀,現在,我們需要為Piece類別定義一個類似的適配器,因為我們對GameStateAdapter的定義取決於是否能夠打包Piece實例。將以下定義新增至games/views.py:

class Piece:     # keep definition as before   class PieceAdapter(Adapter):     js_constructor = 'draughts.Piece'      def js_args(self, piece):         return [piece.color, piece.position]      class Media:         js = ['draughts.js']   register(PieceAdapter(), Piece)
登入後複製

重新載入頁面,您將看到錯誤提示消失了,這表示我們已成功將GameState物件序列化為JSON並將其傳遞給範本。現在,我們可以將其包含在模板中-編輯games/templates/game.html:

<body>        <h2>Draughts</h2>        <div id="game" data-game-state="{{ game_state_json }}">        </div>    </body>
登入後複製

再次重新載入頁面,並在瀏覽器的開發人員工具中檢查遊戲元素(在Chrome和Firefox中,右鍵點選TODO註釋,然後選擇Inspect或Inspect  Element),您將看到GameState物件的JSON表示,準備好解壓成完整的JavaScript物件。

除了將資料打包成JSON可序列化的格式外,JSContext物件還追蹤將資料解壓縮所需的JavaScript媒體定義,作為其媒體屬性。讓我們更新遊戲視圖,以將其也傳遞給模板-在games/views.py中:

def game(request):     game_state = GameState.new_game()      js_context = JSContext()     packed_game_state = js_context.pack(game_state)     game_state_json = json.dumps(packed_game_state)      return render(request, 'game.html', {         'game_state_json': game_state_json,         'media': js_context.media,     })
登入後複製

將下面程式碼新增至games / templates / game.html中的HTML頭檔:

<head>         <title>Draughts</title>         {{ media }}         <script>             document.addEventListener('DOMContentLoaded', event => {                 const gameElement = document.getElementById('game');                 gameElement.innerHTML = 'TODO: render the board here'             });         </script>     </head>
登入後複製

重新加载页面并查看源代码,您将看到这带来了两个JavaScript包括 ——  telepath.js(客户端telepath库,提供解包机制)和我们在适配器定义中指定的draughts.js文件。后者尚不存在,所以让我们在games /  static / draughts.js中创建它:

class Piece {     constructor(color, position) {         this.color = color;         this.position = position;     } } window.telepath.register('draughts.Piece', Piece);   class GameState {     constructor(pieces) {         this.pieces = pieces;     } } window.telepath.register('draughts.GameState', GameState);
登入後複製

这两个类定义实现了我们先前在适配器对象中声明的构造函数-构造函数接收的参数是js_args定义的参数。window.telepath.register行将这些类定义附加到通过js_constructor指定的相应标识符。现在,这为我们提供了解压缩JSON所需的一切-回到games  / templates / game.html中,更新JS代码,如下所示:

<script>            document.addEventListener('DOMContentLoaded', event => {                const gameElement = document.getElementById('game');                const gameStateJson = gameElement.dataset.gameState;                const packedGameState = JSON.parse(gameStateJson);                const gameState = window.telepath.unpack(packedGameState);                console.log(gameState);            })        </script>
登入後複製

您可能需要重新启动服务器以获取新的games/static文件夹。重新加载页面,然后在浏览器控制台中,您现在应该看到填充了Piece对象的GameState对象。现在,我们可以继续在games/static/draughts.js中填写渲染代码:

class Piece {     constructor(color, position) {         this.color = color;         this.position = position;     }      render(container) {         const element = document.createElement('div');         container.appendChild(element);         element.style.width = element.style.height = '24px';         element.style.border = '2px solid grey';         element.style.borderRadius = '14px';         element.style.backgroundColor = this.color;     } } window.telepath.register('draughts.Piece', Piece)   class GameState {     constructor(pieces) {         this.pieces = pieces;     }      render(container) {         const table = document.createElement('table');         container.appendChild(table);         const cells = [];         for (let y = 0; y < 8; y++) {             let row = document.createElement(&#39;tr&#39;);             table.appendChild(row);             cells[y] = [];             for (let x = 0; x < 8; x++) {                 let cell = document.createElement(&#39;td&#39;);                 row.appendChild(cell);                 cells[y][x] = cell;                 cell.style.width = cell.style.height = &#39;32px&#39;;                 cell.style.backgroundColor = (x + y) % 2 ? &#39;silver&#39;: &#39;white&#39;;             }         }          this.pieces.forEach(piece => {             const [x, y] = piece.position;             const cell = cells[y][x];             piece.render(cell);         });     } } window.telepath.register('draughts.GameState', GameState)
登入後複製

在games/templates/game.html中添加对render方法的调用:

<script>             document.addEventListener('DOMContentLoaded', event => {                 const gameElement = document.getElementById('game');                 const gameStateJson = gameElement.dataset.gameState;                 const packedGameState = JSON.parse(gameStateJson);                 const gameState = window.telepath.unpack(packedGameState);                 gameState.render(gameElement);             })         </script>
登入後複製

重新加载页面,您将看到我们的跳棋程序已准备就绪,可以开始游戏了。

  • 让我们快速回顾一下我们已经取得的成果:

  • 我们已经打包和解包了自定义Python /  JavaScript类型的数据结构,而无需编写代码来递归该结构。如果我们的GameState对象变得更复杂(例如,“棋子”列表可能变成棋子和国王对象的混合列表,或者状态可能包括游戏历史),则无需重构任何数据打包/拆包逻辑,除了为每个使用的类提供一个适配器对象。

  • 仅提供了解压缩页面数据所需的JS文件-如果我们的游戏应用程序扩展到包括Chess,Go和Othello,并且所有生成的类都已通过Telepath注册,则我们仍然只需要提供与跳棋知识相关的代码。

即使我们使用任意对象,也不需要动态内联JavaScript ——  所有动态数据都以JSON形式传递,并且所有JavaScript代码在部署时都是固定的(如果我们的网站强制执行CSP,这一点很重要)。

以上是Python和JavaScript間交換資料的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

vs code 可以在 Windows 8 中運行嗎 vs code 可以在 Windows 8 中運行嗎 Apr 15, 2025 pm 07:24 PM

VS Code可以在Windows 8上運行,但體驗可能不佳。首先確保系統已更新到最新補丁,然後下載與系統架構匹配的VS Code安裝包,按照提示安裝。安裝後,注意某些擴展程序可能與Windows 8不兼容,需要尋找替代擴展或在虛擬機中使用更新的Windows系統。安裝必要的擴展,檢查是否正常工作。儘管VS Code在Windows 8上可行,但建議升級到更新的Windows系統以獲得更好的開發體驗和安全保障。

visual studio code 可以用於 python 嗎 visual studio code 可以用於 python 嗎 Apr 15, 2025 pm 08:18 PM

VS Code 可用於編寫 Python,並提供許多功能,使其成為開發 Python 應用程序的理想工具。它允許用戶:安裝 Python 擴展,以獲得代碼補全、語法高亮和調試等功能。使用調試器逐步跟踪代碼,查找和修復錯誤。集成 Git,進行版本控制。使用代碼格式化工具,保持代碼一致性。使用 Linting 工具,提前發現潛在問題。

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

sublime怎麼運行代碼python sublime怎麼運行代碼python Apr 16, 2025 am 08:48 AM

在 Sublime Text 中運行 Python 代碼,需先安裝 Python 插件,再創建 .py 文件並編寫代碼,最後按 Ctrl B 運行代碼,輸出會在控制台中顯示。

See all articles