カテゴリー
サインイン 新規登録

間違いや改善の指摘

内容の技術的な誤り・誤字脱字やミスのご報告・解説やトピックの追記/改善のご要望は教材をさらに良くしていく上でとても貴重なご意見になります。

少しでも気になった点があれば、ご遠慮なく投稿いただけると幸いです🙏

実際には誤りではなく勘違いであっても、ご報告いただけることで教材のブラッシュアップにつながります。

質問ポリシー①

教材受講者みなさんのスムーズな問題解決のために、心がけていただきたいことがあります。

教材の内容に関する質問を投稿しましょう

教材の内容に関係のない質問や教材とは異なる環境・バージョンで進めている場合のエラーなど、教材に関係しない質問は推奨していないため回答できない場合がございます。

その場合、teratailなどの外部サイトを利用して質問することをおすすめします。教材の誤字脱字や追記・改善の要望は「文章の間違いや改善点の指摘」からお願いします。

3-2

商品モデルの作成

モデルとは

初期マイグレーションのパートでも少しお話ししましたが、モデルとはそのシステム内で扱いたいひとまとまりのデータとその振る舞いを定義したものになります。Djangoの開発では基本的にSQL文は使用せず、このモデルに対する操作でデータの管理を行います。一つのモデルに対し、一つのテーブルが作成され、モデルを定義する際はdjango.db.models.Modelクラスを継承して独自のモデルを定義します。

商品モデルの作成

このパートでは商品に対応するモデルを作成します。
モデルはアプリフォルダに生成されているmodels.pyに記述します。
早速商品モデルを作成しましょう。

models.pyを以下のコードのように修正してください。

Copied!
techpit/ └ amazon/  ├ static/  ├ __init__.py  ├ apps.py  ├ models.py ← このファイルを修正します。  ├ views.py   ├ admin.py  ├ migrations/  └ test.py
amazon/models.py
1234567891011121314151617181920212223242526
Copied!
## 中略 ## # [3-1] 商品クラス追加 ここから class Product(models.Model): class Meta: verbose_name = '商品' verbose_name_plural = "商品" thumbnail = models.ImageField( verbose_name = 'サムネイル', upload_to = "thumbnails/" ) name = models.CharField( verbose_name = '名前', max_length=150, null = False, blank=False ) price = models.IntegerField( verbose_name = '価格' ) description = models.TextField( verbose_name = '説明' ) # [3-1] 商品クラス追加 ここまで

各フィールド(データカラムに相当)はdjango.db.modelsで定義されている各フィールドから選択し、継承して定義します。

フィールドの種類は様々ありますが、上記で記載されている各フィールドを説明いたします。

  • ImageField
    • 画像を保管するために利用します。アップロードされた画像ファイルを保管する目的で利用します。このフィールドでは画像データそのものがデータベースに格納されるわけではなく、そのメタデータ(ファイル名やパス、外部からアクセスさせるURL)を保持します。
  • CharField
    • 短い文字列を保管するための利用します。引数としてmax_length(最大長)を設定する必要があります。非常によく利用するクラスになります。
  • IntegerField
    • こちらもCharFieldに並びよく利用されるクラスで、整数を保持します。
  • TextField
    • CharFieldでは格納しきれない長い文字列を保管するために利用します。

各引数について

  • verbose_name
    • そのフィールドの表示名を定義します。ここで定義した値はdjango管理画面等で利用されます。
  • null = True/False
    • nullを許容するかどうかを定義します。Trueとした場合、この項目に該当するデータベースのカラムが空であることを許容します。
  • blank = True/False
    • フォームからの入力で空の値を許容するかどうかを定義します。
  • upload_to
    • これらはImageFieldやFileFieldのようなファイルを扱う項目に利用する設定値で、アップロードされたファイルをどこに保存するかを定義します。

以上で商品モデルの定義が完了しました。

マイグレーションの実施

新しくモデルを定義したらマイグレーションをしましょう。

仮想環境に入っている状態で、manage.pyファイルと同じフォルダへ移動し、以下のコマンドを打ちます。

shell
12345
Copied!
(myenv)$ python manage.py makemigrations amazon Migrations for 'amazon': amazon/migrations/0001_initial.py - Create model Product

これで新しいマイグレーションファイルが作成されました。

次に実際にマイグレーションしていきます。

shell
12345
Copied!
(myenv)$ python manage.py migrate amazon Operations to perform: Apply all migrations: amazon Running migrations: Applying amazon.0001_initial... OK

これで商品モデルに対応するテーブルがデータベースに作成されました。
実際にテーブルが追加されていることを確認しましょう。

shell
12345678910
Copied!
(myenv)$ sqlite3 db.sqlite3 SQLite version 3.24.0 2018-06-04 14:10:15 Enter ".help" for usage hints. sqlite> .tables amazon_product auth_user_user_permissions auth_group django_admin_log auth_group_permissions django_content_type auth_permission django_migrations auth_user django_session auth_user_groups

テーブルは[アプリ名]_[モデル名]で作成されます。
amazon_productというテーブルが作成されていることがわかります。

初期データの投入準備

モデルを作成し、マイグレーションによってテーブルを作成したので、初期データを投入しましょう。

Djangoでは、fixtureというjsonデータから初期データを一括で投入できるコマンドが用意されています。

今回はこのコマンドを利用して商品データを投入してみましょう。

まずはアプリフォルダの中にfixturesフォルダを作成し、その中にinitial_data.jsonというファイルを作成しましょう。

Copied!
amazon/  ├ static/  ├ fixtures/ ← 追加  ┃ └ initial_data.json ← 追加  ├ __init__.py  ├ apps.py  ├ models.py   ├ views.py   ├ admin.py  ├ migrations/  └ test.py

作成したらinitial_data.jsonに以下のコードを追加してください。

amazon/fixtures/initial_data.json
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
Copied!
[ { "model": "amazon.Product", "pk": 1, "fields": { "thumbnail": "1.jpg", "name": "アイロン", "price": 10000.0, "description": "非常に使いやすいアイロンです。" } }, { "model": "amazon.Product", "pk": 2, "fields": { "thumbnail": "2.jpg", "name": "ブレンダー", "price": 200.0, "description": "様々なものをブレンドできます。" } }, { "model": "amazon.Product", "pk": 3, "fields": { "thumbnail": "3.jpg", "name": "バッグ", "price": 30000.0, "description": "おしゃれなバッグです。" } }, { "model": "amazon.Product", "pk": 4, "fields": { "thumbnail": "4.jpg", "name": "スマートフォン", "price": 20000.0, "description": "使いやすいスマートフォンです。" } }, { "model": "amazon.Product", "pk": 5, "fields": { "thumbnail": "5.jpg", "name": "ソファ", "price": 2600000.0, "description": "上質な素材を使ったソファです。" } }, { "model": "amazon.Product", "pk": 6, "fields": { "thumbnail": "6.jpg", "name": "チェア", "price": 260000.0, "description": "上質な素材を使ったチェアです。" } }, { "model": "amazon.Product", "pk": 7, "fields": { "thumbnail": "7.jpg", "name": "腕時計", "price": 76000.0, "description": "おしゃれな腕時計です。" } }, { "model": "amazon.Product", "pk": 8, "fields": { "thumbnail": "8.jpg", "name": "ディスプレイ", "price": 6000.0, "description": "リーズナブルなディスプレイです。" } } ]

1オブジェクトが1jsonオブジェクトに対応するので、上記ファイルでは計8レコードを定義しております。model項目にモデルクラスを指定し、pkには主キー、fieldsには各フィールドを定義します。nameやprice等はそのままなので説明は不要かと思いますが、ImageFieldのthumbnailについては少し特殊です。ImageFieldやFileFieldの項目については、登録する画像ファイルのパスを指定するのですが、その際のルートフォルダとなるのが、MEDIA_ROOT(詳しくは1-4参照)です。

1-4でtechpit/mediaフォルダを作成していますので、そのフォルダの直下に画像ファイルを置きましょう。
ダウンロードした静的ファイル(staticフォルダ)のstatic/images/items/下の商品画像を全てmediaフォルダにコピーします。

media.zip

Copied!
techpit/   ├ amazon/   ├ static/   ├ media/   ├ 1.jpg ← 配置   └ ・・・  

検証環境(Django開発用サーバ利用時)の場合はもう一手間

開発中の確認時等、Djangoの開発用サーバ(manage.py runserverコマンド)を利用すると、静的ファイルやメディアファイルの扱い(クライアントからの要求に対してファイルを返すようなWebサーバの仕事)もdjangoの開発サーバに実施してもらいます。そのため、このmediaファイルに対してもルーティングを追加してやる必要があります。(今回はstaticフォルダの中身は外部に公開しないためmediaフォルダのルーティングのみ追加します)

techpit/urls.pyを以下のように修正しましょう。

Copied!
techpit └── urls.py
techpit/urls.py
1234567
Copied!
〜略〜 from django.conf.urls.static import static # 追加 urlpatterns = [ path('techpit/admin/', admin.site.urls), path('techpit/amazon/', include('amazon.urls')) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # 追加

これで、MEDIA_URLへきたリクエストをdjangoが処理できるようになります。

データ投入

データの投入は以下のコマンドで実行します。

shell
12
Copied!
(myenv)$ python manage.py loaddata initial_data.json Installed 8 object(s) from 1 fixture(s)

上記のようになっていれば成功です。
実際にDBをのぞいてみましょう。

shell
12345678910111213
Copied!
(myenv)$ sqlite3 db.sqlite3 SQLite version 3.27.2 2019-02-25 16:06:06 Enter ".help" for usage hints. sqlite> select * from amazon_product; 1|1.jpg|アイロン|10000|非常に使いやすいアイロンです。 2|2.jpg|ブレンダー|200|様々なものをブレンドできます。 3|3.jpg|バッグ|30000|おしゃれなバッグです。 4|4.jpg|スマートフォン|20000|使いやすいスマートフォンです。 5|5.jpg|ソファ|2600000|上質な素材を使ったソファです。 6|6.jpg|チェア|260000|上質な素材を使ったチェアです。 7|7.jpg|腕時計|76000|おしゃれな腕時計です。 8|8.jpg|ディスプレイ|6000|リーズナブルなディスプレイです。 sqlite>

8件データを確認できました。

以上で今回のパートは終了です。

お疲れ様でした。