Djangoにおけるリクエスト処理、PyMySQL連携、およびORM操作の実践ガイド

静的ファイルの設定

Djangoでは、CSS、JavaScript、画像、サードパーティ製のフロントエンドライブラリなど、あらかじめ用意されたリソースを「静的ファイル」と呼びます。デフォルトでは、プロジェクトルート直下にstaticフォルダを作成し、そこにこれらのリソースを配置することが推奨されます。さらに管理を容易にするため、cssjsimgなどのサブフォルダで区分けするのが一般的です。

settings.pyでの設定例を以下に示します。

import os

# 静的ファイルへのアクセスプレフィックス(URLの一部)
STATIC_URL = '/assets/'

# 静的ファイルが配置されている実際のファイルシステムパス
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
    os.path.join(BASE_DIR, 'resources'),  # 複数のディレクトリを指定可能
]

テンプレート内で静的ファイルを読み込む際は、動的なパス生成を利用することで、設定変更に強い実装が可能です。まず{% load static %}を宣言し、{% static 'パス' %}タグを使用します。

{% load static %}
<!-- 動的パスによるリソース読み込み -->
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<script src="{% static 'js/main.js' %}"></script>

requestオブジェクトの活用

Djangoのビュー関数は必ずHttpRequestオブジェクトを引数として受け取ります。このオブジェクトを通じて、クライアントからのリクエスト情報(メソッド種別、送信データなど)にアクセスできます。

リクエストメソッドの判別

リクエストがGETかPOSTかを判別するには、request.methodプロパティを参照します。この値は文字列(例:'GET', 'POST')で返されます。

POSTデータの取得

フォームから送信されたデータを取得するにはrequest.POSTを使用します。これは辞書ライクなオブジェクトです。キーを指定して値を取得する際、getメソッドを使うと単一の値が、getlistメソッドを使うとリスト形式で値を取得できます。

def process_form(request):
    if request.method == 'POST':
        # 単一の値を取得(リストの最後の要素、または存在しない場合はNone)
        username = request.POST.get('user_name')
        
        # 複数の値を取得(チェックボックスなど)
        selected_items = request.POST.getlist('items')
        
        # 処理ロジック...

注意点: POSTリクエストを行う際、CSRF(Cross Site Request Forgery)対策が有効になっていると403エラーが発生する場合があります。開発段階で検証する場合は、settings.pyMIDDLEWARE設定から'django.middleware.csrf.CsrfViewMiddleware'を一時的にコメントアウトするか、テンプレート側でCSRFトークンを適切に埋め込む必要があります。

データベース接続の設定(PyMySQL)

Djangoデフォルトのデータベースドライバではなく、Python純正のMySQLコネクタであるPyMySQLを使用する手順を解説します。

まず、settings.pyDATABASES設定を以下のように変更します。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'my_project_db',     # データベース名
        'USER': 'db_admin',          # ユーザー名
        'PASSWORD': 'secure_pass',   # パスワード
        'HOST': '127.0.0.1',         # ホスト
        'PORT': '3306',              # ポート
        'CHARSET': 'utf8mb4',        # 文字コード
    }
}

次に、プロジェクトフォルダ(settings.pyと同階層)またはアプリケーションフォルダ直下の__init__.pyに、以下のコードを記述してDjangoにPyMySQLの使用を指示します。

import pymysql

# MySQLdbの代わりにPyMySQLを使用するよう設定
pymysql.install_as_MySQLdb()

Django ORMの基礎

ORM(Object-Relational Mapping)を利用することで、SQLを直接記述せずにPythonオブジェクトとしてデータベース操作を行えます。

モデルの定義

アプリケーションディレクトリ内のmodels.pyでクラスを定義します。ここでは例として「従業員」を管理するモデルを作成します。

from django.db import models

class Employee(models.Model):
    # idフィールドは主キーとして自動的に追加されます(明示的な定義も可能)
    full_name = models.CharField(max_length=100)  # 名前
    email_address = models.EmailField(max_length=255) # メールアドレス
    job_title = models.CharField(max_length=64)   # 役職
    
    def __str__(self):
        return f"{self.full_name} ({self.job_title})"

データベースのマイグレーション

モデルの変更をデータベースに反映させるには、以下の2つのコマンドを実行します。

  1. python manage.py makemigrations: モデルの変更内容を検出し、マイグレーションファイル(変更履歴)を作成します。
  2. python manage.py migrate: マイグレーションファイルを基に、実際のデータベーススキーマを更新します。

フィールドの追加と削除

既存のテーブルに新しいフィールドを追加する場合、デフォルト値が設定されていないとエラーになります。その際は、default値を設定するか、null=Trueを指定してNULLを許容する必要があります。

CRUD機能の実装

ORMを使用したデータの検索、登録、更新、削除の具体的な実装例を示します。

認証機能の実装

ユーザーからの入力を受け取り、データベース内のレコードと照合するログイン処理です。

from django.shortcuts import render, HttpResponse
from . import models

def login_view(request):
    if request.method == 'POST':
        input_email = request.POST.get('email')
        input_pass = request.POST.get('password')
        
        # filterメソッドで条件に合うレコードを検索
        # first()を呼ぶことでクエリセットから最初のオブジェクトを取得
        user_obj = models.Employee.objects.filter(email_address=input_email).first()
        
        if user_obj:
            # 実際のアプリケーションではハッシュ化されたパスワードの比較が必要
            if user_obj.password == input_pass: 
                return HttpResponse('ログインに成功しました')
            else:
                return HttpResponse('パスワードが間違っています')
        else:
            return HttpResponse('該当するユーザーが見つかりません')
            
    return render(request, 'login.html')

データ一覧の表示と新規登録

データベースから全件取得して表示し、新しいレコードを追加する機能です。

def employee_list(request):
    # objects.all()ですべてのレコードを取得
    all_employees = models.Employee.objects.all()
    return render(request, 'list.html', {'employees': all_employees})

def add_employee(request):
    if request.method == 'POST':
        name = request.POST.get('full_name')
        role = request.POST.get('role')
        
        # createメソッドで新しいレコードを作成・保存
        models.Employee.objects.create(
            full_name=name,
            job_title=role
        )
        # 登録後は一覧ページへリダイレクト
        return redirect('/list/')
        
    return render(request, 'add.html')

データの編集と削除

既存のレコードを修正・削除する処理です。URLパラメータを利用して対象のIDを受け取ります。

def edit_employee(request):
    # GETパラメータから編集対象のIDを取得
    target_id = request.GET.get('id')
    # IDに基づいて対象オブジェクトを取得
    emp_instance = models.Employee.objects.filter(id=target_id).first()
    
    if request.method == 'POST':
        new_name = request.POST.get('full_name')
        new_role = request.POST.get('role')
        
        # updateメソッドで条件に合うレコード(複数可)を一括更新
        models.Employee.objects.filter(id=target_id).update(
            full_name=new_name,
            job_title=new_role
        )
        return redirect('/list/')
        
    return render(request, 'edit.html', {'target_emp': emp_instance})

def delete_employee(request):
    del_id = request.GET.get('id')
    
    # deleteメソッドで条件に合うレコードを削除
    models.Employee.objects.filter(id=del_id).delete()
    
    return redirect('/list/')

テンプレート側では、編集や削除を行うボタンにIDを含むURLを設定します。

<tbody>
    {% for emp in employees %}
    <tr>
        <td>{{ emp.full_name }}</td>
        <td>{{ emp.job_title }}</td>
        <td>
            <!-- GETパラメータでIDを渡す -->
            <a href="/edit/?id={{ emp.id }}">編集</a>
            <a href="/delete/?id={{ emp.id }}">削除</a>
        </td>
    </tr>
    {% endfor %}
</tbody>

タグ: Django Python ORM PyMySQL web-development

5月20日 06:06 投稿