telepath ist eine Django-Bibliothek für den Datenaustausch zwischen Python und JavaScript, die es Ihnen ermöglicht, Anwendungen mit umfangreichen clientseitigen Schnittstellen zu erstellen und gleichzeitig die Geschäftslogik im serverseitigen Code beizubehalten.
Es bietet eine Möglichkeit, strukturierte Daten, einschließlich Python-Objekte, in einen serialisierbaren JSON-Formatierungsmechanismus zu packen. Dieser Mechanismus kann erweitert werden, um jede Python-Klasse zu unterstützen, indem er bei der entsprechenden JavaScript-Implementierung registriert wird. Die gepackten Daten können dann in die HTTP-Antwort eingefügt und in JavaScript dekomprimiert werden, um eine Datenstruktur zu erhalten, die den Originaldaten entspricht.
pip install telepath
und fügen Sie „Telepath“ zu den INSTALLED_APPS des Projekts hinzu.
Nehmen wir an, wir erstellen eine Django-App zum Damespielen. Wir haben Tage oder Wochen damit verbracht, eine Python-Implementierung der Spielregeln zu erstellen und Klassen bereitzustellen, die den aktuellen Spielstatus und verschiedene Teile darstellen. Allerdings möchten wir dem Spieler auch eine wirklich benutzerfreundliche Oberfläche bieten, was bedeutet, dass es für uns an der Zeit ist, ein JavaScript-Frontend zu schreiben. Unser UI-Code verfügt zwangsläufig über eigene Objekte, die unterschiedliche Rollen repräsentieren und die Datenstrukturen widerspiegeln, die wir auf dem Server verfolgen – wir können jedoch keine Python-Objekte senden, daher wird das Senden dieser Daten an den Client normalerweise erfolgen. Dies bedeutet, dass eine JSON-Darstellung des Spielstatus entworfen wird und das Entwerfen einer Menge Styling-Code an beiden Enden, das Durchlaufen der Datenstruktur, um zwischen nativen Objekten hin und her zu konvertieren. Sehen wir uns an, wie Telepath den Prozess vereinfacht.
Ein komplettes Dame-Spiel ist etwas zu viel für dieses Tutorial, daher entscheiden wir uns einfach, diesen Schritt zu rendern ...
Erstellen Sie in der Python-Umgebung ein neues Django-Projekt:
pip install "Django>=3.1,<3.2" django-admin startproject draughts cd draughts ./manage.py startapp games
„Spiele“ zur INSTALLED_APPS-Liste in drafts/settings.py hinzufügen.
Der Einfachheit halber werden wir in diesem Beispiel keine Datenbank einbeziehen und den Spielstatus als normale Python-Klasse anstelle eines Django-Modells darstellen. Ändern Sie games/views.py wie folgt:
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('black', (x, y)) for y in range(0, 3) for x in range((y + 1) % 2, 8, 2) ] white_pieces = [ Piece('white', (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, 'game.html', {})
Erstellen Sie games/templates/game.html wie folgt:
<!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>
Fügen Sie die neue Ansicht zu Entwürfen/URLs hinzu. 🎜🎜#
from django.contrib import admin from django.urls import path from games.views import game urlpatterns = [ path('', game), path('admin/', admin.site.urls), ]
pip install telepath
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, })
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)
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)
<body> <h2>Draughts</h2> <div id="game" data-game-state="{{ game_state_json }}"> </div> </body>
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, })
<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('tr'); table.appendChild(row); cells[y] = []; for (let x = 0; x < 8; x++) { let cell = document.createElement('td'); row.appendChild(cell); cells[y][x] = cell; cell.style.width = cell.style.height = '32px'; cell.style.backgroundColor = (x + y) % 2 ? 'silver': 'white'; } } 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,这一点很重要)。
Das obige ist der detaillierte Inhalt vonSo tauschen Sie Daten zwischen Python und JavaScript aus. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!