telepath 라이브러리 기반 Python과 JavaScript 간 데이터 교환
12163 단어 PythontelepathJavaScript
그것은 어떤 작용을 합니까?
이것은 Python 대상을 포함한 구조화된 데이터를 JSON 서열화 형식으로 묶는 메커니즘을 제공한다.상응하는 JavaScript에 이 메커니즘을 등록함으로써 이 메커니즘을 확장하여 모든 Python 클래스를 지원할 수 있습니다.그리고 압축된 데이터는 HTTP 응답에 포함되고 자바스크립트에서 압축을 풀면 원시 데이터와 같은 효과를 얻을 수 있다.
설치 방법
pip install telepath
프로젝트에 "telepath"를 추가하는 INSTALLED_APPS.소개
만약 우리가 바둑을 두는 데 사용할 Django 응용 프로그램을 구축하고 있다고 가정해 보세요.우리는 이미 수일 또는 수주의 시간을 들여 게임 규칙의Python 실현을 구축했고 현재 게임 상태와 각 부분을 대표하는 클래스를 제공했다.그러나 우리는 플레이어에 적당한 우호적인 사용자 인터페이스를 제공하기를 희망한다. 이것은 우리가 자바스크립트 전단을 작성할 때가 되었다는 것을 의미한다.우리의 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'를 추가합니다.간단하게 말하자면, 이 예시에서 우리는 데이터베이스와 관련되지 않고, 게임 상태를 Django모델이 아닌 일반적인Python 클래스로 표시할 것이다.게임/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('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', {})
다음과 같이 게임/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>
<h1>Draughts</h1>
<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.pyrunserver에서 서버를 시작하고 http://localhost:8000/에 접근합니다.지금까지 우리는 새로운 게임을 대표하는 GameState 대상을 만들었습니다. 이 대상을 클라이언트로 전송할 수 있도록telepath를 도입할 때입니다.다음 명령을 수행합니다.
pip install telepath
draughts/settings에'telepath'를 추가합니다.py의 INSTALLED_APPS 목록에 있습니다.현재 게임/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에 등록함으로써 이루어집니다.다음과 같이 게임/뷰를 업데이트합니다.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 객체입니다.미디어 클래스 지시 파일입니다. 이 파일은 Django가 포맷 미디어에 대한 약속을 따라 GameState의 JavaScript를 찾을 수 있습니다.잠시 후 이 자바스크립트가 구현된 외관을 볼 수 있습니다. 이제 Piece 클래스에 유사한 어댑터를 정의해야 합니다. 왜냐하면 GameStateAdapter에 대한 정의는 Piece 실례를 포장할 수 있는지에 달려 있기 때문입니다.다음 정의를 게임/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으로 정렬하여 템플릿에 전달했음을 나타냅니다.이제 템플릿에 포함할 수 있습니다. - 게임/templates/game 편집.html:
<body>
<h1>Draughts</h1>
<div id="game" data-game-state="{{ game_state_json }}">
</div>
</body>
페이지를 다시 불러오고 브라우저의 개발자 도구에서 게임 요소를 검사합니다(크롬과 파이어폭스에서 TODO 주석을 오른쪽 단추로 클릭하고 Inspect 또는 Inspect Element). 게임스테이트 대상을 볼 수 있는 JSON은 완전한 자바스크립트 대상으로 압축을 풀 준비가 되어 있음을 나타냅니다.데이터를 JSON 서열화 가능한 형식으로 포장하는 것 외에 JSContext 대상은 데이터 압축 해제에 필요한 JavaScript 미디어 정의를 미디어 속성으로 추적합니다.템플릿에도 전달할 게임 보기를 업데이트합니다. - 게임/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,
})
다음 코드를 게임/templates/게임에 추가합니다.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>
페이지를 다시 불러오고 원본 코드를 보면 자바스크립트 두 개가 포함되어 있습니다.js(클라이언트telepath 라이브러리, 패키지 해제 메커니즘 제공)와 저희가 어댑터 정의에서 지정한draughts.js 파일.후자는 아직 존재하지 않기 때문에 게임스/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 압축에 필요한 모든 것을 알 수 있습니다. - 게임/templates/게임으로 돌아가세요.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>
새 게임/static 폴더를 가져오려면 서버를 다시 시작해야 할 수도 있습니다.페이지를 다시 로드한 다음 브라우저 콘솔에서 Piece 객체가 채워진 GameState 객체를 볼 수 있습니다.현재, 우리는 게임/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)
게임/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>
페이지를 다시 불러오면 바둑 프로그램이 준비되어 있어서 게임을 시작할 수 있습니다.우리는 우리가 이미 얻은 성과를 신속하게 되돌아봅시다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.