目次
これは何をするものですか?
インストール方法
はじめに
ホームページ バックエンド開発 Python チュートリアル Python と JavaScript の間でデータを交換する方法

Python と JavaScript の間でデータを交換する方法

May 11, 2023 pm 11:04 PM
javascript python

telepath は、Python と JavaScript の間でデータを交換するための Django ライブラリで、ビジネス ロジックをサーバー側コードに保持しながら、豊富なクライアント側インターフェイスを備えたアプリケーションを構築できます。

これは何をするものですか?

これは、Python オブジェクトを含む構造化データを JSON シリアル化可能な形式にパッケージ化するメカニズムを提供します。このメカニズムは、対応する JavaScript 実装に登録することで、任意の Python クラスをサポートするように拡張できます。パックされたデータは HTTP 応答に含められ、JavaScript で解凍されて、元のデータと同等のデータ構造を取得できます。

インストール方法

pip install telepath
ログイン後にコピー
ログイン後にコピー

そして、プロジェクトの INSTALLED_APPS に「telepath」を追加します。

はじめに

チェッカーをプレイするための Django アプリケーションを構築しているとします。私たちは数日から数週間をかけて、ゲーム ルールの Python 実装を構築し、現在のゲーム状態やさまざまな部分を表すクラスを提供しました。ただし、適切にユーザーフレンドリーなインターフェイスをプレーヤーに提供したいとも考えています。つまり、JavaScript フロントエンドを作成する時期が来たことを意味します。私たちの UI コードには、必然的にさまざまな役割を表す独自のオブジェクトが含まれ、サーバー上で追跡しているデータ構造をミラーリングします。ただし、Python オブジェクトを送信することはできないため、このデータをクライアントに送信することは通常、ゲーム状態の JSON 表現を設計することを意味します。 、そして両端で多くのスタイル コードを設計し、データ構造を走査してネイティブ オブジェクト間で相互に変換します。テレパスがどのようにプロセスを簡素化するかを見てみましょう。

完全なチェッカー ゲームはこのチュートリアルには少し多すぎるため、レンダリング ステップだけを選択します...

Python 環境で、新しい Django プロジェクトを作成します:

pip install "Django>=3.1,<3.2" django-admin startproject draughts cd draughts ./manage.py startapp games
ログイン後にコピー

drafts/settings.py の INSTALLED_APPS リストに「ゲーム」を追加します。

わかりやすくするために、この例ではデータベースを使用せず、Django モデルではなく通常の Python クラスとしてゲームの状態を表します。 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>
ログイン後にコピー

新しいビューをdrafts/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 オブジェクトを作成しました。今度は、そのオブジェクトをクライアントに転送できるようにテレパスを導入します。コマンド

pip install telepath
ログイン後にコピー
ログイン後にコピー

を実行し、drafts/settings.py の INSTALLED_APPS リストに「telepath」を追加します。ここで、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,     })
ログイン後にコピー

Here JSContext は、ゲーム状態オブジェクトの Javascript で使用できる表現への変換を管理するために使用されるヘルパー ツールです。 js_context.pack はそのオブジェクトを取得し、JSON シリアル化してテンプレートに渡すことができる値に変換します。ただし、現在はページのリロードが次の形式のエラーで失敗します: don't know how to package object:

これは、GameState が Telepath がまだ処理方法を知らないカスタム Python タイプであるためです。パックに渡されるカスタム タイプは、対応する JavaScript 実装にリンクする必要があります。これは、Adapter オブジェクトを定義し、それをテレパスに登録することによって行われます。 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 は、クライアント上で GameState インスタンスを構築するために使用される JavaScript コンストラクターの識別子であり、 js_args 定義はこのコンストラクターに渡されます。引数を使用して、指定された game_state オブジェクトの JavaScript 対応部分を再作成します。 Media クラスは、メディアをフォーマットするための Django の規則に従うファイルを示し、GameState の JavaScript 実装がここにあります。この JavaScript 実装がどのようなものになるかは後で説明します。GameStateAdapter の定義は Piece インスタンスをパッケージ化できるかどうかに依存しているため、今のところは 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 を右クリックします)コメントして [検査] または [要素の検査] を選択すると、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 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

あるデータフレームの列全体を、Python内の異なる構造を持つ別のデータフレームに効率的にコピーする方法は? あるデータフレームの列全体を、Python内の異なる構造を持つ別のデータフレームに効率的にコピーする方法は? Apr 01, 2025 pm 11:15 PM

PythonのPandasライブラリを使用する場合、異なる構造を持つ2つのデータフレーム間で列全体をコピーする方法は一般的な問題です。 2つのデータがあるとします...

Pythonスクリプトは、特定の場所のカーソル位置への出力をどのようにクリアしますか? Pythonスクリプトは、特定の場所のカーソル位置への出力をどのようにクリアしますか? Apr 01, 2025 pm 11:30 PM

Pythonスクリプトは、特定の場所のカーソル位置への出力をどのようにクリアしますか? Pythonスクリプトを書くときは、以前の出力をカーソル位置にクリアするのが一般的です...

uvicornは、serving_forever()なしでhttpリクエストをどのように継続的に聞いていますか? uvicornは、serving_forever()なしでhttpリクエストをどのように継続的に聞いていますか? Apr 01, 2025 pm 10:51 PM

UvicornはどのようにしてHTTPリクエストを継続的に聞きますか? Uvicornは、ASGIに基づく軽量のWebサーバーです。そのコア機能の1つは、HTTPリクエストを聞いて続行することです...

文字列を介してオブジェクトを動的に作成し、Pythonでメソッドを呼び出す方法は? 文字列を介してオブジェクトを動的に作成し、Pythonでメソッドを呼び出す方法は? Apr 01, 2025 pm 11:18 PM

Pythonでは、文字列を介してオブジェクトを動的に作成し、そのメソッドを呼び出す方法は?これは一般的なプログラミング要件です。特に構成または実行する必要がある場合は...

PythonインタープリターはLinuxシステムで削除できますか? PythonインタープリターはLinuxシステムで削除できますか? Apr 02, 2025 am 07:00 AM

Linux Systemsに付属するPythonインタープリターを削除する問題に関して、多くのLinuxディストリビューションは、インストール時にPythonインタープリターをプリインストールし、パッケージマネージャーを使用しません...

PythonおよびOCRテクノロジーを使用して、複雑な検証コードをクラックしようとする方法は? PythonおよびOCRテクノロジーを使用して、複雑な検証コードをクラックしようとする方法は? Apr 01, 2025 pm 10:18 PM

毎日のネットワークインタラクションでPythonを使用したクラッキング検証コードの調査、検証コードは、自動化されたプログラムの悪意のある操作を防ぐための一般的なセキュリティメカニズムです...

GoまたはRustを使用してPythonスクリプトを呼び出して、真の並列実行を実現する方法は? GoまたはRustを使用してPythonスクリプトを呼び出して、真の並列実行を実現する方法は? Apr 01, 2025 pm 11:39 PM

GoまたはRustを使用してPythonスクリプトを呼び出して、真の並列実行を実現する方法は?最近、私はPythonを使用しています...

See all articles