Djangoの動作確認20230310

Django REST Frameworkでいろいろコードを書いて動作を確認しています。

このブログでは自分の整理用に手を動かした記録をつけておきたいと思いますので、手順や内容はごちゃごちゃしてしまうかも知れません。

Pythonが動作する環境はVSCodeのDev Containerで構築しました。Dockerイメージはデフォルトでmcr.microsoft.com/devcontainers/python:0-3.11が指定されています。

pip freezeコマンドでまだ何もライブラリがインストールされていないことを確認。

pip freeze

DjangoDjango REST Frameworkをインストールします。 後々慣れてきたらrequirements.txtを用意するかDockerfileでインストールするコマンドを書いておきたいと思います。

pip install django
pip install djangorestframework

pip freezeすると以下の結果になりました。

ライブラリのインストールされている場所を確認します。

python
>>> import django
>>> print(django.__file__)
/home/vscode/.local/lib/python3.11/site-packages/django/__init__.py

確かvenvを有効化していたらvenvのlibあたりにインストールされたと思いますが、今回はvenvを有効化していないので上記のパスになっていると推測します。 Pythonの仮想環境のベストプラクティスについても深掘りしたいところですが、今はDjangoの使い方に慣れたいので後回しにします。

pythonの対話型ターミナルをquit()で抜けます。

quit()

django-adminコマンドで新規プロジェクトを作成します。

vscode ➜ /workspaces/python-5 $ django-admin startproject drfproject
vscode ➜ /workspaces/python-5 $ tree
.
└── drfproject
    ├── drfproject
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py

この時点でローカルサーバーを起動することができます。

vscode ➜ /workspaces/python-5 $ cd drfproject/
vscode ➜ /workspaces/python-5/drfproject $ python manage.py runserver

runserverを実行するとdrfprojectディレクトリにdb.sqlite3ができていました。

vscode ➜ /workspaces/python-5 $ tree
.
└── drfproject
    ├── db.sqlite3
    ├── drfproject
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-311.pyc
    │   │   ├── settings.cpython-311.pyc
    │   │   ├── urls.cpython-311.pyc
    │   │   └── wsgi.cpython-311.pyc
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py

3 directories, 11 files

新規にblogというappを作成してみます。

vscode ➜ /workspaces/python-5/drfproject $ python manage.py startapp blog

vscode ➜ /workspaces/python-5/drfproject $ cd ..
vscode ➜ /workspaces/python-5 $ tree
.
└── drfproject
    ├── blog
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── db.sqlite3
    ├── drfproject
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-311.pyc
    │   │   ├── settings.cpython-311.pyc
    │   │   ├── urls.cpython-311.pyc
    │   │   └── wsgi.cpython-311.pyc
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py

5 directories, 18 files

drfproject/blog/models.pyにUserモデルを定義してみます。

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()

makemigrationsコマンドを実行すると、no changes detectedになりました。

vscode ➜ /workspaces/python-5 $ python drfproject/manage.py makemigrations
No changes detected

確かsettings.pyにINSTALLED_APPという項目があったはずなので、追加してみます。

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "blog", # 追加
]

再度makemigrationsを実行すると処理が行われました。

vscode ➜ /workspaces/python-5 $ python drfproject/manage.py makemigrations
Migrations for 'blog':
  drfproject/blog/migrations/0001_initial.py
    - Create model User

一度管理画面からモデルにデータを入れたいので、ローカルサーバーを起動し、http://localhost:8000/adminにアクセスすると以下の画面が表示されます。

まだsuperuserを作成していなかったので作成します。

vscode ➜ /workspaces/python-5 $ python drfproject/manage.py createsuperuser

You have 19 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, blog, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

migrate実行前のmigrationがあるとcreatesuperuserコマンドは実行できないようでした。 migrateを実行します。

vscode ➜ /workspaces/python-5 $ python drfproject/manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying blog.0001_initial... OK
  Applying sessions.0001_initial... OK

再度createsuperuserを実行すると成功しました。

vscode ➜ /workspaces/python-5 $ python drfproject/manage.py createsuperuser
Username (leave blank to use 'vscode'): test
Email address: test@email.com
Password:
Password (again):

作成したsuperuserで管理画面にアクセスすると、Userモデルが参照できませんでした。 確かblog/admin.pyに登録する必要があったはずなので、ドキュメントを調べてみます。

Djangoの公式ドキュメントに情報がありました。 https://docs.djangoproject.com/en/4.1/ref/contrib/admin/#modeladmin-objects

ドキュメントの例を参考にdrfproject/blog/admin.pyを以下のようにしてみました。

from django.contrib import admin
from .models import User

class UserAdmin(admin.ModelAdmin):
    pass
admin.site.register(User, UserAdmin)

すると管理画面でもUserモデルが表示されました。 また、ドキュメントにはModelAdminクラスはなくても良いよ的な記述もあったので以下のコードも試してみたところ同じく管理画面にUserモデルは表示されていました。

from django.contrib import admin
from .models import User

# class UserAdmin(admin.ModelAdmin):
#     pass
# admin.site.register(User, UserAdmin)
admin.site.register(User)

おそらくpassするだけじゃなくて何かロジックを書きたい時はUserAdminクラスを定義する必要があるけど、そうじゃないなら省略しても動作に変わりはないっぽいなと解釈しました。

管理画面からUserデータを登録しました。

APIのリクエストを受けるにはViewの設定が必要だったはずなので、作成してみます。 DRFではViewにクラスを定義するのが基本な気がするけど、いろいろ試したいので関数を定義してみます。

drfproject/blog/views.py

from django.http import HttpResponse


def home(request):
    return HttpResponse("HELLO\n")

drfproject/drfproject/urls.py

from django.contrib import admin
from django.urls import path
from blog import views
urlpatterns = [
    path("admin/", admin.site.urls),
    path("blog/", views.home)
]

するとhttp://localhost:8000/blog/にリクエストを投げるとレスポンスが返ってくることが確認できました。

vscode ➜ /workspaces/python-5 $ curl http://localhost:8000/blog/
HELLO

Viewに関数を定義してrouterでエンドポイントと紐づけることができるようです。 ここまではモデルも介さずただ文字列を返す関数を実行しているだけなので、次はViewにDRFで提供されてるクラスを定義してみます。