0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

DjangoとDocker練習OA23o1o0 チェックインを作ろう!

Last updated at Posted at 2022-06-05

サンプルを見る

📖 この記事のゴール

目標

現在、対局中かどうかを調べられるようにしたい

詳細

ゲーム対局部屋にチェックインさせる

ここで、以下の2つはこの記事では実装しない

  • 対局が終わったことを示すチェックアウト
  • 多面指しのために複数の部屋に入ることへの考慮

ゲーム対局部屋に入るときは当該 Room モデルのレコードの sente_id または gote_id フィールドに 自分のユーザーIdを上書きし、
自分の Profile レコードの match_state フィールドを 3 (対局中)に上書きする

情報

この記事は Lesson 1. から順に全部やってこないと ソースが足りず実行できないので注意されたい

What is This is
Lesson 1. 📖 DjangoとDockerでゲーム対局サーバーを作ろう!

この記事のアーキテクチャ:

What is This is
OS Windows10
Container Docker
Database Postgresql, (Redis)
Program Language Python 3
Web framework Django
Auth allauth
Frontend Vuetify
Data format JSON
Others (Socket), Web socket
Editor Visual Studio Code (以下 VSCode と表記)

ディレクトリ構成を抜粋すると 以下のようになっている

    ├── 📂 src1                            # あなたのDjangoサーバー開発用ディレクトリー。任意の名前
    │   ├── 📂 apps1
    │   │   ├── 📂 accounts_vol1o0    # アプリケーション
    │   │   ├── 📂 portal_v1                # アプリケーション
    │   │   ├── 📂 practice_vol1o0              # アプリケーション
    │   │   │   ├── 📂 migrations
    │   │   │   └── 📂 models
    │   │   │       └── 📂 room
    │   │   │           └── 📄 ver1o0.py
    │   │   ├── 📂 tic_tac_toe_vol1o0           # アプリケーション
    │   │   └── 📂 tic_tac_toe_vol2o0           # アプリケーション
    │   │       ├── 📂 migrations
    │   │       │   └── 📄 __init__.py
    │   │       ├── 📂 static
    │   │       │   └── 📂 tic_tac_toe_vol2o0
    │   │       │       ├── 📂 gui
    │   │       │       └── 📂 think
    │   │       ├── 📂 templates
    │   │       │   └── 📂 tic_tac_toe_vol2o0
    │   │       │       ├── 📂 gui
    │   │       │       └── 📂 think
    │   │       ├── 📂 views
    │   │       │   ├── 📂 gui
    │   │       │   └── 📂 think
    │   │       ├── 📄 __init__.py
    │   │       ├── 📄 admin.py
    │   │       ├── 📄 apps.py
    │   │       └── 📄 tests.py
    │   ├── 📂 data
    │   ├── 📂 project1                     # プロジェクト
    │   │   ├── 📄 __init__.py
    │   │   ├── 📄 asgi.py
    │   │   ├── 📄 settings_secrets_example.txt
    │   │   ├── 📄 settings.py
    │   │   ├── 📄 urls_accounts_vol1o0.py
    │   │   ├── 📄 urls_practice.py
    │   │   ├── 📄 urls_tic_tac_toe_v1.py
    │   │   ├── 📄 urls_tic_tac_toe_v2.py
    │   │   ├── 📄 urls.py
    │   │   ├── 📄 ws_urls_tic_tac_toe_v1.py
    │   │   └── 📄 wsgi.py
    │   ├── 📂 project2                     # プロジェクト
    │   ├── 🐳 docker-compose-project2.yml
    │   ├── 🐳 docker-compose.yml
    │   ├── 🐳 Dockerfile
    │   ├── 📄 manage.py
    │   └── 📄 requirements.txt
    ├── 📂 src1_meta
    │   ├── 📂 data
    │   │   └── 📄 urls.csv
    │   └── 📂 scripts
    │       └── 📂 auto_generators
    │           └── 📄 urls.py
    ├── 📂 src2_local                      # Djangoとは関係ないもの
    │    ├── 📂 sockapp1
    │    └── 📂 websockapp1
    └── 📄 .gitignore

実装手順

Step [OA23o1o0g1o0] Dockerコンテナの起動

👇 (していなければ) Docker コンテナを起動しておいてほしい

# docker-compose.yml ファイルを置いてあるディレクトリーへ移動してほしい
cd src1

# Docker コンテナ起動
docker-compose up

Step [OA23o1o0g2o0] 対局申込ビュー編集 - match_application/ver2o0 フォルダー

👇 以下の既存ファイルを編集してほしい

    └── 📂 src1
        └── 📂 apps1
            └── 📂 tic_tac_toe_vol3o0                 # アプリケーション Three
                └── 📂 views
                    └── 📂 gui
                        └── 📂 match_application
                            └── 📂 ver2o0
👉                              └── 📄 __init__.py
# BOF [OA23o1o0g2o0]

# 〇×ゲーム2.0巻 対局申込1.0版
from apps1.tic_tac_toe_vol2o0.views.gui.match_application.ver1o0 import MatchApplicationView as ViewOfMatchApplicationV2g1o0
#                         ^two
#    -----------------------------------------------------------        --------------------    ----------------------------
#    1                                                                  2                       3
# 1. `src1/apps1/tic_tac_toe_vol2o0/views/gui/match_application/ver1o0/__init__.py`
#          -----------------------------------------------------------
# 2. `1.` の __init__.py ファイルに含まれるクラス
# 3. '2.' の別名

# 〇×ゲーム3.0巻 対局申込1.0版
from apps1.tic_tac_toe_vol3o0.views.match_application.ver1o0 import MatchApplicationView as ViewOfMatchApplicationV3g1o0
#                         ^three                         ^one
#          ------------------                         ------        --------------------    ----------------------------
#          11                                         12            2                       3
#    -------------------------------------------------------
#    10
# 10. `src1/apps1/tic_tac_toe_vol3o0/views/match_application/ver1o0/__init__.py`
#           -------------------------------------------------------
# 10, 12. ディレクトリー
# 11. アプリケーション
# 2. `12.` に含まれる __init__.py ファイルにさらに含まれるクラス
# 3. '2.' の別名


class MatchApplicationView():
    """[OA23o1o0g2o0] 対局申込ビュー"""

    @staticmethod
    def render(request):
        """描画"""

        # 以下のファイルは既存です
        from apps1.tic_tac_toe_vol2o0.views.gui.match_application.ver1o0.v_render import render_match_application
        #                         ^two
        #    --------------------------------------------------------------------        ------------------------
        #    1                                                                           2
        # 1. `src1/apps1/tic_tac_toe_vol2o0/views/gui/match_application/ver1o0/v_render.py`
        #          --------------------------------------------------------------------
        # 2. `1.` に含まれる静的関数

        return render_match_application(
            request,
            ViewOfMatchApplicationV3g1o0.playing_web_path,
            ViewOfMatchApplicationV2g1o0.template_path,
            MatchApplicationView.on_sent,
            MatchApplicationView.open)

    @staticmethod
    def on_sent(request):
        """送信後"""

        # 以下のファイルはあとで作ります
        from .v_on_sent import match_application_on_sent
        #    ----------        -------------------------
        #    1                 2
        # 1. `src1/apps1/tic_tac_toe_vol3o0/views/match_application/ver2o0/v_on_sent.py`
        #                                                                  ---------
        # 2. `1.` に含まれる関数

        return match_application_on_sent(request)

    @staticmethod
    def open(request):
        """訪問後"""
        return ViewOfMatchApplicationV2g1o0.open_context

# EOF [OA23o1o0g2o0]

Step [OA23o1o0g3o0] 対局申込ビュー作成 - match_application/ver2o0/v_on_sent.py ファイル

👇 以下のファイルを新規作成してほしい

    └── 📂 src1
        └── 📂 apps1
            └── 📂 tic_tac_toe_vol3o0                   # アプリケーション Three
                └── 📂 views
                    └── 📂 match_application
                        └── 📂 ver2o0
                            ├── 📄 __init__.py
👉                          └── 📄 v_on_sent.py
# BOF [OA23o1o0g3o0]

# 部屋モデル
from apps1.practice_vol1o0.models.room.ver1o0 import Room
#          ---------------             ------        ----
#          11                          12            2
#    ----------------------------------------
#    10
# 10, 12. ディレクトリー
# 11. アプリケーション
# 2. `12.` に含まれる __init__.py ファイルにさらに含まれるクラス

# ユーザー拡張
from apps1.practice_vol1o0.models.user_profile.ver1o0 import Profile
#          ---------------                     ------        -------
#          11                                  12            2
#    ------------------------------------------------
#    10
# 10, 12. ディレクトリー
# 11. アプリケーション
# 2. `12.` に含まれる __init__.py ファイルにさらに含まれるクラス


def match_application_on_sent(request):
    """[OA23o1o0g3o0] 対局申込 - 送信後

    * ログインしていないユーザーが部屋に入っても 何も記録しません
    * ログインしているユーザーが部屋に入ってくると、以下のものを記録します(チェックイン)
    * Room.sente_id または Room.gote_id の空いている方に user.pk を上書き
    * user.profile.match_state を 3 (対局中)に上書き
    """

    # `po_` は POST送信するパラメーター名の目印
    # 部屋名
    po_room_name = request.POST.get("po_room_name")
    # 自分の番。 "X" か "O"。 機能拡張も想定
    my_turn = request.POST.get("po_my_turn")

    # 部屋の取得 または 新規作成
    #
    # * ID ではなく、部屋名から行う
    room_table_qs = Room.objects.filter(name=po_room_name)

    if 1 <= len(room_table_qs):
        # (名前被りがあったなら)先頭の1つを取得
        room = room_table_qs[0]
    else:
        # 新規作成
        room = Room()
        room.name = po_room_name

    if request.user.is_authenticated:
        # ログインしたユーザーだった

        user_pk = request.user.pk

        # 自分の Profile レコード 取得
        profile = Profile.objects.get(user__pk=user_pk)
        #                             --------
        #                             1
        # 1. Profile テーブルと 1対1 で紐づいている親テーブル User の pk フィールド

        if my_turn == "X":
            # X を取った方は先手とします
            room.sente_id = user_pk
            # ユーザーの状態を対局中(3)にします
            profile.match_state = 3

        elif my_turn == "O":
            # O を取った方は後手とします
            #
            # * 先手と後手が同じユーザーでも構わないものとします
            room.gote_id = user_pk
            # ユーザーの状態を対局中(3)にします
            profile.match_state = 3

        else:
            # それ以外は観戦者として扱う
            # ユーザーの状態を観戦中(4)にします
            profile.match_state = 4

        # 先手と後手の両方が埋まったなら
        if not(room.sente_id is None or room.sente_id == 0 or room.gote_id is None or room.gote_id == 0):
            # 盤と棋譜を空っぽにする
            room.board = ""
            room.record = ""

        # TODO バリデーションチェック
        room.save()

        # TODO バリデーションチェック
        profile.save()

        # print(f"[match_application_on_sent] ★ 更新終わり")
    else:
        # ゲストだった
        # print(f"[match_application_on_sent] ★ ゲスト")
        pass

# EOF [OA23o1o0g3o0]

Step [OA23o1o0g4o0]

Merged to OA23o1o0g4o1o0

Step [OA23o1o0g4o1o0] ルート編集 - urls.csv ファイル

👇 以下の既存ファイルの末尾に追記してほしい

    ├── 📂 src1
    │   └── 📂 apps1
    │       └── 📂 tic_tac_toe_vol3o0                   # アプリケーション Three
    │           └── 📂 views
    │               └── 📂 match_application
    │                   └── 📂 ver2o0
    │                       ├── 📄 __init__.py
    │                       └── 📄 v_on_sent.py
    └── 📂 src1_meta
        └── 📂 data
👉          └── 📄 urls.csv
...略... file,path,name,comment,module,class,alias,method
...略...


../src1/project1/urls_tic_tac_toe_vol3o0_autogen.py,tic-tac-toe/vol3.0/match-application/ver2.0/,,"OA23o1o0g4o1o0 〇×ゲーム3.0巻 対局申込中2.0版",apps1.tic_tac_toe_vol3o0.views.match_application.ver2o0,MatchApplicationView,TicTacToe3o0MatchApplicationView2o0,render

Step [OA23o1o0g4o2o0] ルート編集 - コマンド打鍵

👇 以下のコマンドを打鍵してほしい

cd ../src1_meta
python -m scripts.auto_generators.urls
cd ../src1
docker-compose restart
  • ディレクトリーは、がんばって移動してほしい
  • スクリプトについて See also: O3o2o_1o0g2o0
  • 設定ファイルを変更したら、サーバーの再起動が必要

テスト手順

Step [OA23o1o0g5o0] Web画面へアクセス

先手と後手で、2人分のプレイヤーのアカウントがほしい。
このゲームは2人用なので、Webページを2窓で開き、片方が X プレイヤー、もう片方が O プレイヤーとして遊んでほしい

1つのPCで 2つのアカウントをアクティブにする方法が分からないが、
今のところ 厳密に作れてはいないので、以下の手順で行う

👇 (既にログインしているかもしれないので)ログアウトを試す

📖 http://localhost:8000/accounts/vol1.0/logout/

👇 以下のリンクから サインアップ してテスト用のアカウントを用意してほしい

ユーザー名: test1
E-mail: (あなたに届く、あなたの2個目のEメールアドレス)
パスワード: test1example
パスワード(再入力) test1example

📖 http://localhost:8000/accounts/vol1.0/signup/

確認のメールが届くので、アクティベーション用のリンクをクリックしてほしい

👇 アカウントをアクティベートしたら、以下の URL を開いてほしい(ログイン処理が完了する)

📖 http://localhost:8000/accounts/vol1.0/login/

👇 そして 以下の URL を開いて、 Test1 部屋に X 番として入ってほしい

📖 http://localhost:8000/tic-tac-toe/vol3.0/match-application/ver2.0/

ここで、ログアウトしたなら対局部屋を追い出されるべきだが、まだそこまで作っていない。

👇 それをいいことに、対局部屋のブラウザ画面を残したまま 今のユーザーをログアウトしてほしい

📖 http://localhost:8000/accounts/vol1.0/logout/

👇 以下の URL を開いて、スーパーユーザー でログインしなおしてほしい(既に作っているはずだ)

📖 http://localhost:8000/accounts/vol1.0/login/

👇 以下の URL を開いて、 Test1 部屋に O 番として入ってほしい

📖 http://localhost:8000/tic-tac-toe/vol3.0/match-application/ver2.0/

👇 部屋、ユーザーを確認するには、管理画面を使うのが確実だ。
スーパーユーザーのまま、 以下の URL を開いて、管理画面に入っていてほしい

📖 http://localhost:8000/admin

サイドメニューから、 Rooms モデルを開いてほしい
Test 1 room があるはずなので、開いてほしい

部屋に入っているユーザーの主キーが記録されていることを確認してほしい

例:

部屋名: Test1
対局者_先手Id: 2
対局者_後手Id: 1
盤面:
棋譜:

また、(余裕があれば)既存でない部屋名でも ちゃんとユーザーの主キーが記録されることを確認してほしい

後処理

Step [OA23o1o0g6o0] ランチャーのリンク用データ追加 - finished-lessons.csv ファイル

👇 以下の既存ファイルの最終行に追記してほしい

    └── 📂 src1
        ├── 📂 apps1
        │   ├── 📂 portal_v1                        # アプリケーション
        │   │   └── 📂 data
👉      │   │       └── 📄 finished-lessons.csv
        │   └── 📂 tic_tac_toe_vol3o0                   # アプリケーション Three
        │       └── 📂 views
        │           └── 📂 match_application
        │               └── 📂 ver2o0
        │                   ├── 📄 __init__.py
        │                   └── 📄 v_on_sent.py
        └── 📂 project1                             # プロジェクト
            └── 📄 urls_practice.py

👇 冗長なスペース,冗長なダブルクォーテーション,末尾のカンマ は止めてほしい

/tic-tac-toe/vol3.0/match-application/ver2.0/,OA23o1o0g6o0 〇×ゲーム3.0巻 対局申込中2.0版

👇 ランチャーにリンクが追加されていることを確認してほしい

📖 http://localhost:8000/

次の記事

📖 Djangoでゲーム対局部屋をモニターしよう!

参考にした記事

📖 Create Django model or update if exists
📖 How can I get the username of the logged-in user in Django?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?