学習記録
Q1. ソケットオブジェクトはサーバーとクライアントの両方になれますか?2つの書き方を見ました:server = socket.socket()とclient= socket.socket()
回答: はい、ソケットオブジェクトはサーバー側またはクライアント側のどちらとしても使用できます。Pythonのsocketモジュールでは、socket.socket()関数がソケットオブジェクトを作成し、このオブジェクトはサーバー(接続の監視と受け入れ)またはクライアント(接続の開始)として構成できます。
ソケットオブジェクトの振る舞い(サーバーまたはクライアント)は、どのように使用するかによって決まります。以下は2つの異なる使用方法の簡単な例です:
### サーバーソケット
サーバーソケットはアドレスとポートにバインドし、クライアントからの接続要求を監視します。
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCPソケットを作成
server_socket.bind(('127.0.0.1', 8080)) # アドレスとポートにバインド
server_socket.listen() # 接続の監視を開始
while True:
client_socket, client_address = server_socket.accept() # 接続を受け入れる
# 接続を処理
client_socket.close() # クライアントソケットを閉じる
### クライアントソケット
クライアントソケットはサーバーへの接続要求を送信します。
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCPソケットを作成
client_socket.connect(('127.0.0.1', 8080)) # サーバーに接続
# データの送受信
client_socket.close() # ソケットを閉じる
これらの例では、両方ともsocket.socket()関数を使用して新しいソケットオブジェクトを作成しています。サーバー側では、bind()メソッドがソケットを特定のIPアドレスとポートにバインドし、listen()メソッドがソケットによる接続の監視を開始し、accept()メソッドが着信接続を待ち受けます。クライアント側では、connect()メソッドがサーバーへの接続を開始します。
変数名server_socketとclient_socketは単なる変数名であり、ソケットオブジェクトの振る舞いには影響しません。任意の変数名を使用できますが、コードの可読性と保守性のために、ソケットの役割を示す説明的な変数名を使用することをお勧めします。
Q2: 以前に送った簡単なTCPサーバーを実行した後、ブラウザで127.0.0.1からの応答が無効だと表示されました。ERR_INVALID_HTTP_RESPONSEエラーが発生しましたが、sock.send(b'HTTP/1.1 200 OK\r\n\r\nhello big baby!')に修正したら解決しました。このHTTP/1.1 200 OK\r\n\r\nとは何ですか?
HTTP/1.1 200 OK\r\n\r\nはHTTP応答の始まり部分であり、HTTPプロトコルの形式に従っています。ブラウザでWebページにアクセスすると、ブラウザはサーバーにHTTPリクエストを送信し、サーバーはHTTPプロトコルの仕様に従って応答を送信する必要があります。この応答には、ステータス行、レスポンスヘッダー(オプション)、その後に空行とレスポンスボディが含まれます。
各部分の説明は以下の通りです:
HTTP/1.1:HTTPプロトコルのバージョンを指定します。ここではHTTP 1.1です。200 OK:ステータスコードとステータスメッセージです。200はリクエストが成功したことを示し、OKはステータスメッセージの説明です。\r\n:キャリッジリターンとラインフィードで、HTTP応答の各部分を区切るために使用されます。\r\n\r\n:HTTPヘッダーとレスポンスボディの間には空行が必要であり、ここでは2つの\r\nでこの空行を表しています。
したがって、sock.send(b'hello big baby!')をsock.send(b'HTTP/1.1 200 OK\r\n\r\nhello big baby!')に修正すると、実際には元のTCP応答を有効なHTTP応答に変更したことになります。これにより、ブラウザは応答を正しく解析し、レスポンスボディ内のhello big baby!テキストを表示できます。
簡単なTCPサーバーでブラウザからのHTTPリクエストを処理する場合、送信する応答がHTTPプロトコルの形式に従っていることを確認する必要があります。これが、HTTP/1.1 200 OK\r\n\r\nを追加した後にブラウザが応答を正しく表示できる理由です。
Q3: なぜrequest.dataを使ってrequest.POST.getを使わないのですか?
Django REST framework(DRF)では、request.dataは解析されたリクエストボディデータを返します。これは、クライアントからのJSON、XML、またはその他のコンテンツタイプのデータを処理するのに適しています。request.dataはDRFのRequestオブジェクトの属性であり、リクエストボディでどの形式で送信されていても、データへのアクセスを提供します。
対照的に、request.POSTはDjangoのネイティブHttpRequestオブジェクトの属性であり、フォームデータのみを含みます。主にapplication/x-www-form-urlencodedまたはmultipart/form-dataコンテンツタイプでデータが送信される場合に使用されます。
フロントエンドとバックエンドが分離されたアーキテクチャでは、クライアントは従来のフォームデータではなく、JSON形式のデータをリクエストボディとして送信することが一般的です。したがって、DRFでrequest.dataを使用する方が良い選択です。なぜなら、request.POSTがフォームデータのみを処理できるのに対し、request.dataはJSONデータおよびその他形式のデータを処理できるからです。
これが、DRFでrequest.POSTではなくrequest.dataを使用することが推奨される理由です。これにより、APIがクライアントが送信するJSONまたはその他形式のデータを正しく受信して解析できるようになります。
Q4: コンバーターを使って単一のURLで処理することはできますか?
Djangoのパスコンバーター(path converters)を使用すれば、オプションのpkパラメータを単一のURLで処理することは可能ですが、パス式を正しく設定する必要があります。Django 2.0以降のバージョンでは、path()関数とそのビルトインコンバーターを使用してこれを実現できます。ただし、path()関数はre_path()のような正規表現ではなく、明示的なパスパターンを重視するように設計されているため、直接path()関数でオプションパラメータを実装するには少し複雑です。
単一のURL構成でpkがある場合とない場合の両方を処理したい場合、最も直接的な方法は、前回の回答で示したようにre_path()と正規表現を使用することです。ただし、path()関数を好む場合は、pkがない場合を別のパスとして定義し、ビュー内でロジック処理を行うことを検討できます。
しかし、ご要望に基づいて、類似のソリューションとして、2つのパスを定義して同じビューを指す方法があります。これは単一のURL構成ではありませんが、実際には同じ効果を達成できます:
from django.urls import path
from .views import ToDoView
urlpatterns = [
path('api/todo/', ToDoView.as_view(), name='todo-list'), # pkがない場合を処理
path('api/todo/<int:pk>/', ToDoView.as_view(), name='todo-detail'), # pkがある場合を処理
]
このように、ToDoViewビューはpkがNoneかどうかによってリストを返すか単一項目の詳細を返すかを決定できます。この方法の利点は、URLを明確で直感的に保ちながら、Djangoのパスコンバーターを使用してpkパラメータ(提供されている場合)が整数型であることを保証できる点です。
これは単一のURL構成による実現ではありませんが、異なるリクエストタイプを処理する明確で構造化された方法を提供し、同時にRESTful APIの設計原則に従います。ほとんどの場合、この方法が好まれます。なぜなら、URL設計をより直感的で理解しやすくするからです。
Q5: pip debugとは何ですか?
pip debugはpipコマンドの一つで、pipの環境と設定に関するデバッグ情報を提供します。このコマンドは、パッケージのインストール時の問題を診断したり、pipの内部情報を理解したりするのに役立ちます。
pip debugコマンドを実行すると、以下の有用な情報が出力されます:
pipのバージョン- Pythonのバージョン
- オペレーティングシステム情報
- 環境変数
pip設定ファイルの場所- インストールされたパッケージの互換性ラベル(例:
cp37、cp38はCPython 3.7、3.8を示す) - 仮想環境で実行されているかどうか
このコマンドは、通常、pipの作業環境を詳細に知る必要がある上級ユーザーや開発者が使用します。また、バグ報告を提出する際に追加のコンテキスト情報を提供するのにも役立ちます。
例えば、pip debugコマンドを実行するには、コマンドラインに以下のように入力します:
pip debug
より詳細な出力が必要な場合は、-vオプションを使用できます:
pip debug -v
これにより、より詳細なデバッグ情報が出力され、複雑な問題の解決に役立つ可能性があります。
1. Djangoのインストール
pip install django
C:/python39
-python.exe
-Scripts
-pip.exe
-django-admin.exe [プロジェクト内のファイルとフォルダを作成するツール]
-Lib
-組み込みモジュール
-site-packages(ここにインストールしたモジュールがすべて保存されます)
-openpyx1
-python-docx
-flask
-django [フレームワークのソースコード]
python setup.py installを実行すると、DjangoがPythonのLib下のsite-packagesにインストールされます。
pip install django==2.1.1 -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com
以下のコマンドで確認します
>>> import django
>>> django.get_version()
Djangoのバージョンが出力されればインストールは正しく完了しています。
cmdでpip show djangoと入力してもDjangoがインストールされているか確認できます。
2. PyCharmを使用したプロジェクト作成
Djangoでは、プロジェクトにはいくつかのデフォルトのファイルとフォルダが含まれます。
2.1 ターミナルでのプロジェクト作成
ターミナルを開き
特定のディレクトリに移動(プロジェクトを保存する場所)
PyCharmProjectsに新しいフォルダDjango_Learningを作成
cd C:\Users\OT905626\PycharmProjects\Django_Learning> このディレクトリに移動
プロジェクト作成コマンドの実行
C:\Users\OT905626\AppData\Local\Programs\Python\Python310\Scripts\django-admin.exe startproject プロジェクト名
# もしC:\Users\OT905626\AppData\Local\Programs\Python\Python310\Scriptsが環境変数に追加されている場合
django-admin.exe startproject プロジェクト名
2.2 PyCharmでのプロジェクト作成(プロフェッショナル版が必要)
New Project------Djangoを選択------Locationで保存場所を選択(Pythonのインストールディレクトリ内は選択しないこと)------InterpreterでPythonインタープリタのバージョンを選択------Create
その他の設定はそのままにします
- コマンドでプロジェクトを作成するのが標準的な方法です
- PyCharmでプロジェクトを作成するのは、標準的な方法に加えてtemplateディレクトリが追加されており、最初に削除する必要があります。また、settings.pyファイルにもDIR[]にデータが追加されているので、それも削除してください
2.3 デフォルトのプロジェクトファイルの紹介:
mysite
manage.py (プロジェクトの管理、プロジェクトの起動、appの作成、データ管理、よく使用しますが変更しないでください)
__init__.py
urls.py (URLと関数の対応関係、よく変更します)
settings.py (プロジェクト設定ファイル、よく変更します)
asgi.py (非同期式、ネットワークリクエストの受信に使用、変更しないでください)
wsgi.py (同期式、ネットワークリクエストの受信に使用、変更しないでください)
3. Appの作成
1つの小さな機能が1つのappです
-プロジェクト
-app、ユーザー管理 [データテーブル構造、関数、HTMLテンプレート、CSS]
-app、注文管理 [テーブル構造、関数、HTMLテンプレート、CSS]
-app、管理画面 [テーブル構造、関数、HTMLテンプレート、CSS]
-app、ウェブサイト [テーブル構造、関数、HTMLテンプレート、CSS]
-app、API [テーブル構造、関数、HTMLテンプレート、CSS]
...
相互に独立しており、同じプロジェクト内に配置されます
注意:現在の開発は比較的シンプルで、複数のappを使用する必要はありません。一般的に、プロジェクト内に1つのappを作成するだけで十分です
#ターミナルでコマンドを使用してフォルダを作成
C:\Users\OT905626\PycharmProjects\Django_Learning\mysite> python manage.py startapp app01
#これによりmysiteフォルダ内にapp01が作成されます
または:
C:\Users\OT905626\PycharmProjects\Django_Learning\mysite>django-admin startapp app01
tree
├─app01
│ └─migrations 【固定、変更不要】データベース変更履歴
│ │_ __init__.py
│ __init__.py
│ admin.py 【固定、変更不要】djangoが提供するデフォルトの管理画面
│ apps.py 【固定、変更不要】app起動クラス
│ models.py 【**重要】データベース操作、ORM
│ tests.py 【固定、変更不要】ユニットテスト
│ views.py 【**重要**】関数、この関数はurls.pyに記述する必要があります
└─mysite
└─__pycache__
4. クイックスタート
- appが登録されていることを確認します
apps.pyファイルには以下の内容があります:
class App01Config(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'app01'
settings.pyファイルのINSTALLED_APPSの最後に追加:
'app01.apps.App01Config'
- URLとビュー関数の対応関係をurls.pyで記述
#モジュールをインポート
import app01 import views
urlpatterns = [
#path('admin/', admin.site.urls),
この行をコメントアウトし、
次のように置き換えます
path ('index/', views.index), # views.関数
]
- ビュー関数をviews.pyで記述
from django.shortcuts import render, HttpResponse
# ここにビュー関数を作成
def index(request):
return HttpResponse('ようこそ')
- Djangoプロジェクトを起動
- コマンドラインで起動
python manage.py runserver
- PyCharmで起動
インターフェースに開始終了ボタンがあり、クリックするだけで起動します
URLをクリック
URLに/index/を追加し、「ようこそ」と表示されるページに移動します
4.1 別のページを作成
-url ->関数
-関数
urls.pyで対応関係を作成
views.pyでページを作成
http://127.0.0.1:8000/user/add/
http://127.0.0.1:8000/user/list/
http://127.0.0.1:8000/index/
4.2 templatesテンプレート
HTMLテンプレートを返すためにtemplatesフォルダを作成する際に問題が発生:HTMLテンプレート、ビュー関数、URLパスはすべて完全ですが、実行時にHTMLファイルが見つからないというエラーが表示されます。
原因:settings設定ファイルのINSTALLED_APPにapp設定が追加されていない
#上記で返された内容は文字列のみです。「ようこそ」「ユーザーリスト」「ユーザー追加」などはすべて文字列です
#HTMLをreturnしたい場合、関数を定義する際にHttpResponseではなくrenderをreturnする必要があります
def user_list(request):
#appフォルダ内にtemplatesフォルダを作成し、その中にuser_listという名前のhtmlファイルを作成します(appの登録順序に従って、それぞれのtemplatesフォルダを探します)。元々ルートディレクトリにはデフォルトでtemplatesフォルダがありますが、前の学習過程で削除しました。settings.py内のDIR[]を削除したためです。そうしないと、ルートディレクトリのhtmlの内容が返されます。ルートディレクトリのものは事前に設定する必要があり、設定しないと無効です
return render(request, "user_list.html") # 2つの引数
def user_add(request):
return render(request, "user_add.html")
4.3 静的ファイル
開発中:
- css
- js
- 画像
これらはすべて静的ファイルとして扱われます
4.3.1 静的フォルダの作成
通常はappフォルダ内にstaticフォルダを作成し、そこにcss、img、js、pluginsフォルダを作成します
4.3.2 静的フォルダの参照
bootstrapのインストールと設定:
1.bootstrap公式ページを開きDownloadをクリックし、ページ Compiled CSS and JS の Download をクリックすると、bootstrap-5.3.1-dist.zip形式の圧縮ファイルがダウンロードされます
2.解凍すると同名のフォルダがあり、そのフォルダにはcssとjsの2つのフォルダが含まれています。cssフォルダにはスタイルシートファイルがあり、ページのレイアウトと美化に使用されます。jsフォルダにはjsライブラリファイルがあり、ページのjs効果をサポートします
3.cssフォルダを開くと、bootstrapは異なるレベルのスタイルシートファイルを提供しています。bootstrap.cssは完全版のスタイルライブラリを提供します。ファイル名にminが含まれるものは圧縮版ファイルです。ファイル名にgridが含まれるものは、グリッドシステムのみが含まれます。ファイル名にrebootが含まれるものは、簡易版のコンテンツサポートのみが含まれます
4.jsフォルダを開くと、ファイル名にbundleが含まれるjsライブラリはすでにporper.jsが統合されています。bootstrapの一部コンポーネント(例:ドロップダウンメニュー、モーダルなど)のjs動作効果はporper.jsに依存しています。開発者はプロジェクトの実際のニーズや開発段階に応じて、適切なcssライブラリとjsライブラリを選択できます
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-5.3.1-dist/css/bootstrap.css' %}">
</head>
<body>
<h1>ユーザーリスト</h1>
<input type="text" class="btn btn-primary" value="新規作成"/>
<img src="{% static 'img/1.jpg' %}">
<script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-5.3.1/js/bootstrap.js' %}"></script>
</body>
</html>
Django内部では、静的ファイルにワイルドカードの方法を使用しており、{% load static %}を使用すると、プロジェクト名が変更されても操作がより簡単になります。
この部分のコードを実行した際に問題が発生しました:
1.{% load static %}がテキストとしてブラウザに表示される(ブラウザの問題)
2.画像が表示されず、画像パスも間違っていないようで何度も確認しました
3.「新規作成」がボタンではなく、青い入力可能なテキストボックスになっています
上記の問題の原因を見つけました:使用しているPyCharmはコミュニティ版で、プロフェッショナル版ではないため、load staticの下線が表示され、ブラウザとの互換性がなく、bootstrapのバージョンが互換性がないため、2番目と3番目の問題が発生しています。