Happiness Chain 2025/09の月報(6ヶ月目)

こんにちは、yukikoです!
2025年4月15日にHappiness Chainに入会してから5ヶ月半が経過しました。
9月の振り返りをしていきます。

学習時間(9/1 ~ 9/30)

  • 当月学習時間:191h (日平均:6.4h)
  • 累計学習時間:1127.5h

9月も毎日学習を継続することができ、目標学習時間の170hを達成できました。

学習内容

JavaScript
【上級】
8月に引き続きUdemyの視聴と、鬼滅の刃のキャラクター一覧を取得するAPIを叩く課題に取り組みました。
UdemyはJavaScriptの仕組みについて深く学べましたが、コードが複雑で理解できなかった部分が多々あったため、また折を見て振り返りをしたいと思います。
鬼滅API課題では外部のJSONデータを取得し表示するサイトを作成し、非同期処理やDOM操作について理解を深めることができました。
React
【初級】
公式チュートリアルとUdemyで学習しました。
公式チュートリアルでは最初Reactの記法に慣れず、とても難しく感じましたが、stateやpropsなど、少しずつ理解していくことができました。単元ごとのチャレンジ問題も解きながら進めましたがかなり難しく、自力で解けたのが2~3割だったのでまた挑戦したいと思います。
Udemyでは同じアプリをJavaScriptとReactで作成し、Reactでは簡潔にコードを書けることを実感することができました。動画&ハンズオンだとチュートリアルで分かりづらかった部分も理解しやすかったです。

【中級】
Udemyの学習と、ToDo Listアプリの作成課題に取り組みました。
Udemyではレンダリングの仕組みやルーティング、コンポーネントの分割方法(Atomic Design)、Chakra UIを使ったアプリ作成について学びました。
ToDo List課題は実際にコードを書くことでReactの理解を深めることができました。作成したアプリはGitHub Pagesに公開し、公開方法についてのアウトプット記事を作成しました。

【上級】
Udemy2本で学習しました。
Firebaseを使ったブログアプリや外部ライブラリを使ったマークダウンエディタ、ドラッグ・ドロップ機能の実装など、実践的な内容について学ぶことができました。いろいろと便利な外部サービスがあることを知ることができたので、自分でアプリを作成する際には活用していきたいと思いました。時間の関係で全てはハンズオンできなかったので、また改めて取り組みたいと思います。

アウトプット記事👇 neigeenfant.hatenablog.com
TypeScript
実務開始前にTypeScriptとNext.jsの基本は学習しておきたかったので、セキュリティとSPAは一旦飛ばしてTypeScriptに入りました。
HCの教材2つと、Udemyで学習しました。
TypeScriptはJavaScriptを静的型付け言語として記述できるようにした拡張言語ということで、そんなに難しくないかな?と予想していたのですが、型の付け方にいろいろなバリエーションがあり、ライブラリと組み合わせると特有の書き方も出てきて、とても難しかったです。また、型を決めることで安全なコードを書けることを実感し、TypeScriptでの開発が求められている理由が分かりました。
課題はすべて完了できなかったので、残りのインプット・アウトプット課題についても、後日取り組んでいきたいと思います。
Next.js
公式チュートリアルと1本目のUdemyで学習しました。
公式チュートリアルリポジトリをクローンしてハンズオンでコードの穴埋めをしていく形式で、App RouterでのルーティングやVercelでのDB連携、ローディング画面、エラー処理、認証など一通りのアプリ作成について体系的に学ぶことができました。説明は分かりやすかったですが、Next.jsの内容が難しく、特に認証まわりは一周しただけではよく分からなかったので、今後手を動かしながら慣れていきたいと思います。
Udemyではブログアプリを作成しながらPages RouterやSSG(静的生成)とSSR(サーバーサイドレンダリング)の違いについて学習しました。
Next.jsも残りのインプット・アウトプット課題については引き続き取り組んでいきます。

よかったところ

  • 9月も毎日学習を続けることができました。React課題を修了し、TypeScriptとNext.jsの概要の理解までは進めることができたのでよかったです。
  • ざっくりとですがフロントエンドまで学習してみたことで、これまで学んできたことがどんどん繋がって、プログラミングの全体像が掴めてきた気がします。学習しなければならないことは膨大にあり圧倒される日々ですが、今後も一歩ずつ積み上げていきたいです。

問題点・改善点

  • 現状は動くコードを書くのが精一杯で、整理された保守がしやすいコードを書くことができていないと感じます。一朝一夕にできることではないので、意識してコードを書きながら少しずつ改善していければと思います。
  • React以降は特に新しくインプットすることが多かったですが、先に進めることを優先してしまい学習メモの整理と復習をしていなかったため、学んだことをアウトプットの際に活用しきれませんでした。今後はインプット課題ごとにしっかりとメモの整理・復習をしていこうと思いました。

10月の目標

いよいよ、10/6より実務に入ります。最初はついていくだけで精一杯だと思うので、10月は実務に慣れることを目標にします。また、できる限り自主学習にも取り組んでいきたいです。

まとめ

10月は拠点を東京に移し生活についても大きく変化するため、健康面には気をつけて過ごしたいと思います。
18~19日は熱海合宿に参加するので、HCのみなさんと交流できるのを楽しみにしています!^^

ReactアプリをGitHub Pagesで公開する方法

はじめに

GitHub PagesはHTML/CSS/JavaScriptなどの静的ファイルを公開できるサービスですが、 フロントエンドのライブラリやフレームワーク で作ったアプリケーションも、静的ファイルに変換することで公開ができるようになります。
この記事では、Reactアプリケーションを作成してからGitHub Pagesに公開するまでの手順をまとめました。

目次
1. Reactアプリケーションを作成する
2. リモートリポジトリを作成する
3. GitHub Pagesで公開する
4. Reactアプリケーションを更新する

1. Reactアプリケーションを作成する

今回はViteを使用してReactアプリケーションを作成します。
任意のディレクトリに移動し、以下のコマンドを実行します。

$ npm create vite@latest アプリ名

フレームワークの候補が出るので、Reactを選択します。
(上下矢印キーで選択、Enterキーで決定)

次に構成オプションを選択します(今回はJavaScriptを選択しました)

作成されたディレクトリに移動します

$ cd アプリ名

依存関係をインストールします

$ npm install

サーバーを起動します

$ npm run dev

表示されたURL(例http://localhost:5173/)をブラウザで開くとReactアプリが表示されます。

2. リモートリポジトリを作成する

リモートリポジトリを作成し、ローカルリポジトリとの繋ぎ込みを行います。手順については、リンク先の1〜2をご参照ください。

neigeenfant.hatenablog.com

3. GitHub Pagesで公開する

アプリの作成が完了したら、GitHub Pagesで公開しましょう。

ReactアプリをGitHub Pagesで公開するために、gh-pagesというnpmライブラリを使用します。gh-pagesを使うことで、自動でgh-pagesブランチを作成し、GitHub Pagesへのデプロイを行うことができます。

まず、gh-pagesをインストールします。

$ npm install --save-dev gh-pages

以下のコマンドを実行し、ビルドを行います。

$ npm run build

今回はViteでReactアプリを作成したため、distという名前のフォルダが自動でプロジェクト内に作成されます。この中にGitHub Pages公開用の静的ファイルが格納されています。

package.json"scripts""predeploy""deploy"のコマンドを追記します。 "deploy"には作成されたフォルダ名(dist)を記述します。

"scripts": {
  "predeploy": "npm run build",  // 追記
  "deploy": "gh-pages -d dist"  // 追記
}

Create React AppでReactアプリを作成した場合、package.json"homepage": "公開URL"の記述が必要になりますが、Viteでは不要となります。
代わりに、vite.config.jsにbase: '/リポジトリ名/'を追記します。(これを記載しておかないと公開後にGitHubが正しいパスにアクセスできず、404エラーとなります。)

export default defineConfig({
  plugins: [react()],
  base: '/リポジトリ名/',  // 追記
})

ファイルの準備が完了したので、以下を実行します。 このコマンドによりpackage.jsonに記述した"predeploy": "npm run build""deploy": "gh-pages -d dist"のコマンドが実行されます。

$ npm run deploy

自動でgh-pagesブランチにアップロードが行われ、少し時間を置くとGitHub Pagesにてアプリが公開されます。(GitHub PagesはSettings→Pagesでアクセスできます)
Visit siteを押して、公開されたアプリを確認することができます。
公開URLはhttps://<ユーザー名>.github.io/<リポジトリ名>となります。

4. Reactアプリケーションを更新する

GitHub Pagesで公開後、アプリを修正した場合の更新は以下の手順で行うことができます。

1. ローカルでコード修正を行う

2. 以下のコマンドを実行すると自動でビルド& gh-pagesブランチにデプロイが行われ、GitHub Pagesに更新が反映されます

$ npm run deploy

3. mainブランチや作業ブランチなど、通常のブランチからリモートリポジトリへプッシュを行います

$ git add .
$ git commit -m "修正コメント"
$ git push origin ブランチ名

このように、ソースコードは通常のブランチ(mainや作業ブランチ)で管理し、公開用ファイルは自動的にgh-pagesブランチへ配置することができます。
また、.gitignoreには最初からdistが記載されているため、ビルドで生成されたファイルはリポジトリに含めずに、常にローカルで生成・管理されるようになっています。

参考記事

note.com

zenn.dev

Happiness Chain 2025/08の月報(5ヶ月目)

こんにちは、yukikoです!
2025年4月15日にHappiness Chainに入会してから4ヶ月半が経過しました。
8月の振り返りをしていきます。

内定をいただきました!

8月頭にCEOからWeb系の自社開発企業様をご紹介いただき、内定をいただくことができました!目標としていたWebエンジニアとして働き始められることがとても嬉しいです。出社予定は10月上旬なので、それまでに必要な技術のキャッチアップを行い、準備したいと思います。HCでは引き続きロードマップの完走を目指して学習を継続していきます。

学習時間(8/1 ~ 8/31)

  • 当月学習時間:195.5h (日平均:6.3h)
  • 累計学習時間:936.5h

8月も毎日学習を継続することができましたが、目標学習時間の210hは未達となりました。

学習内容

Django
7月に公式チュートリアルをやり終えたので、復習&アウトプット記事作成と、もう一つの課題書籍に取り組みました。 課題書籍ではMTVフレームワークやORMによるデータベースの操作、Dockerを使用した環境構築など、Djangoのベストプラクティスを中心に学ぶことができました。
実務へ向けたキャッチアップのためDjangoのアウトプット課題は一旦飛ばしてJavaScript課題を進めることになったので、また落ち着いてから次のECサイト作成の課題に取り組んでいきたいと思います。

アウトプット記事👇 neigeenfant.hatenablog.com
JavaScript
JavaScriptは初級・中級・上級の課題を順番に進めました。
【初級】
動画で基本の文法と簡単なアプリ制作の方法をハンズオンで学習しました。 処理の流れはPythonと同じなため理解がしやすかったですが、let・constで宣言が必要だったり、{}で閉じる必要があったりと、慣れるまで少しかかりました。アプリ制作ではHTML要素の取得やCSSの書き換え、イベントリスナーなどについて、流れを学ぶことができました。
【中級】
JavaScript Primerを読み、カレンダーとToDoリスト作成の課題に取り組みました。JavaScript Primerはとてもボリュームがあり読むのが大変でしたが、JavaScriptについて深く学ぶことができました。非同期処理や応用編のアプリのコードはかなり難しく、理解するのが大変でした。クラスや関数、モジュールを使用して可読性が高くメンテナンスしやすいコードを書けるようになることが課題だと感じたので、意識して今後の学習に取り組んでいきたいと思いました。
【上級】
UdemyでJavaScriptの仕組みについて学びました。分割代入やthis、非同期処理など、JavaScript Primerで理解しきれなかった部分について、理解を深めることができました。またセクションごとの演習問題に取り組んだことで理解できている部分とできていない部分が明確になったので、改めて手を動かすことの大切さを感じました。Udemyは8割ほど視聴したので、9月は残りの視聴と、JavaScriptのラスト課題から取り組んでいきます。

アウトプット記事👇 neigeenfant.hatenablog.com

よかったところ

  • 8月も毎日学習を続けることができ、進歩報告会には1回参加することができました。
  • 8月下旬には対談動画撮影のため東京に赴き、CEOや他の卒業生の方たちにお会いして、楽しい時間を過ごさせていただきました。改めて、HCは素敵なコミュニティだなと感じました。

問題点・改善点

  • インプット中に集中力が途切れることが多く学習時間が伸びづらいため、学習と休憩のメリハリをつけて取り組むことが必要だと感じました。
  • 相変わらず就寝時間が遅いため、少しでも生活リズムを改善したいです。

9月の目標

  • 学習時間170h以上

まとめ

9月は勉強以外にも入社準備などでやらないといけないことがあるため、なるべく効率的に学習時間を確保できるように進めていきたいと思います。
9月も頑張ります^^

JavaScript Primerを読んで

はじめに

JavaScriptの学習のため、動画で基本文法やアプリ作成を学んだあと、次の教材としてJavaScript Primerを読みました。今回の記事は本書を読んだ感想をまとめます。
これまでプログラミング学習のために読んだ書籍の中で体感では1番ボリュームがあり、読み切るのが大変でしたが、JavaScriptの基本から応用まで体系的に学ぶことができる、とても良い書籍でした。
JavaScript Primerは以下のリンクから無料で読むことができます👇

jsprimer.net

良かったところ

  • 変化を続けるJavaScriptという言語において、大きな仕様変更のあったECMAScript 2015をベースに最新バージョンのECMAScript 2025まで網羅されていて、この一冊を読めば基本を抑えることができるという安心感がありました。内容は最新の仕様に合わせて常にアップデートされ続けているため、長く愛用できる一冊になるかと思います。
  • 基本文法が単元ごとに分けられており、文章とコード例でとても丁寧に解説されていて分かりやすかったです。コードを書く際に気をつけるべきところや、推奨されない書き方についても言及されているため、バグを防ぐ書き方が身に付くと思いました。実装途中で思ったような挙動にならなかった時に、本書を参照することで解決することも多そうだと感じました。
  • 文中のコード例はそのままブラウザ上で実行して結果を見ることができ、自分でコードを変更することもできるため、「この場合はどういう出力になるんだろう?」ということを手軽に試しながら読み進めることができるのも良かったです。

悪かったところ

悪かったところではないのですが、読むにあたり以下の点を留意すると挫折しにくいかと思います。

  • 丁寧に解説されているが故なのですが、とてもボリュームがるため、一周読むのにかなりの時間がかかりました。まずは完璧に理解しようとせずに全体像を把握し、のちのち実装で詰まった際に対象部分をピックアップして読むようにしても、十分に活用することができるかと思います。
  • 本書は「プログラミング経験者がJavaScriptを学ぶことを念頭に書かれている」とされているように、事前知識がないと理解が難しい部分があります。分からない部分は別の教材を使ったり、一旦飛ばして読み進めることも必要だと感じました。

学んだこと

知らなかったことが多くあり全体を通して沢山の学びがありましたが、特に学びが深かったこと、備忘録として残しておきたいことを抜粋します。

関数の書き方

JavaScriptには複数の関数の宣言方法があり、特にアロー関数には苦手意識がありましたが、それぞれの違いを整理することで、使い方を明確にすることができました。

function宣言
  • 同じ名前の関数を複数定義すると、最後に書いたもので上書きされる
  • 巻き上げされるため、呼び出しを関数定義より上に書いても動く
  • thisの挙動は呼び出し元のオブジェクトに依存する
function fn() {
    console.log("fnが呼び出されました");
}

fn();  // fnが呼び出されました
function式
  • constで宣言しているため、同じ名前の関数を定義するとエラーとなる
  • 巻き上げされないため、定義前に呼び出すとエラーとなる
  • thisの挙動は呼び出し元のオブジェクトに依存する
const fn = function() {
    console.log("fnが呼び出されました");
}

fn();  // fnが呼び出されました
アロー関数
  • constで宣言しているため、同じ名前の関数を定義するとエラーとなる
  • 巻き上げされないため、定義前に呼び出すとエラーとなる
  • thisは関数が定義されたときの外側のスコープのthisに固定される(アロー関数自体はthisを持たない)
const fn = () => {
    console.log("fnが呼び出されました");
}

fn();  // fnが呼び出されました
アロー関数の省略記法
  • 関数の仮引数が1つのときは()を省略できる
  • 関数の処理が1つの式である場合に、ブロック({})とreturn文を省略できる
// 次の2つの定義は同じ意味となる
const mulA = (x) => { return x * x; };
const mulB = x => x * x;
// コールバック関数(引数として渡される関数)にアロー関数を渡す
const array = [1, 2, 3];
array.forEach(num => console.log(num));
// 1
// 2
// 3

非同期処理

非同期処理は今回初めて具体的に学んだため、挙動を理解するのにとても苦戦しました。
以下は非同期処理の一部分ですが、分かったことをまとめました。

同期処理と非同期処理の違い
  • 同期処理は、コードを順番に処理していきます。ひとつの処理が終わるまで次の処理は行われません。
  • 非同期処理は、コードを順番に処理していきますが、ひとつの非同期処理が終わるのを待たずに次の処理が実行されます。代表的な非同期処理は、setTimeoutfetchなどの実行してから完了まで時間がかかる処理です。
  • 非同期処理を同期処理と同様に扱うと、非同期処理の完了を待たずに次の処理が走ってしまい、データの取得やエラーのキャッチができないという問題があります。それを解決するために、Promiseasync/awaitを使います。(async/awaitPromiseの上に成り立っているため、Promiseの理解が前提となります)
Promise
  • new Promise()により、Promiseインスタンスを生成することができます。
  • Promiseインスタンスは非同期処理の状態や結果を表現するビルトインオブジェクトです。必ず次の 3つの状態を持ち、一度 fulfilled(成功)rejected(失敗)になると、その結果は変わりません。
    • pending(保留中) … まだ結果が決まっていない、処理前の状態
    • fulfilled(成功)resolveが呼ばれて結果が決まった
    • rejected(失敗)rejectが呼ばれてエラーになった
  • Promiseに渡しているコールバック関数の2つの引数を使用し、成功時にはresolve();、失敗時にはreject();を呼ぶようにします。これにより、Promiseの結果がfulfilled(成功)rejected(失敗)のどちらかに決まります。
  • Promiseインスタンスthenメソッドに成功時の処理を、catchメソッドに失敗時の処理を書くことで、結果が出たあとの処理を分岐させることができます。また、resolverejectにより渡された値やエラーオブジェクトを受け取ることができます。
// new Promise()でPromiseインスタンスを生成する
const promise = new Promise((resolve, reject) => {
  // setTimeoutは非同期に行われる処理
  setTimeout(() => {
    const success = true;  // 擬似的に成功させる
    if (success) {
      resolve("成功しました!");  // 成功時にresolveを呼ぶ
    }else{
      reject(new Error("失敗しました!"));  // 失敗時にrejectを呼ぶ
    }
  }, 1000);
});

// 成功時にthen、失敗時にcatchが実行される
promise
  .then((value) => { console.log(value); })
  .catch((error) => { console.error(error); });

上記のコードではconst success = true;で処理を成功させているので、thenメソッドが呼ばれ、以下のように表示されます。

成功しました!
Async Function(async/await)
  • Async Functionは、非同期処理を同期処理のように書くことを目的に導入されました。
  • Async Functionは必ずPromiseインスタンスを返す関数を定義する構文で、関数の頭にasync をつけることで定義できます。
  • await式はAsync Functionの中でのみ使うことができ、Promiseインスタンスの前につけることで、fulfilled(成功)rejected(失敗)のどちらかに決まるまで非同期処理の完了を待つことができます。
  • 以下は先ほどのコードをasync/awaitを使って書き換えたものです。async/awaitにより、try...catch構文のように非同期処理を同期処理と同じ構文で扱うことができます。
// Promiseを返す関数として定義する
function asyncTask() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = false;  // 擬似的に失敗させる
      if (success) {
        resolve("成功しました!");
      } else {
        reject(new Error("失敗しました!"));
      }
    }, 1000);
  });
}


// Async Function を定義
async function asyncMain() {
  // await式のエラーはtry...catchできる
  try {
    const value = await asyncTask();  // awaitによりPromiseの結果を待つことができる
    console.log(value);  // 成功時は実行されるが、失敗時はスキップされる
  } catch (error) {
    console.error(error);  // 失敗時に実行される
  }
}

asyncMain();

今度はconst success = false;で処理を失敗させているので、エラーがキャッチされ、以下のように表示されました。

Error: 失敗しました!
その他の非同期処理

他にも、複数の非同期処理を順番に処理していくPromiseチェーンや、すべてのPromiseインスタンスがFulfilled(成功)となったときにFulfilled(成功)となるPromise.all、ひとつでもFulfilled(成功)となったときにFulfilled(成功)となるPromise.raceなど、いろいろな非同期処理について知ることができたので、今後も学習しながら慣れていきたいです。

モジュール

モジュールとは変数や関数などをまとめたもので、JavaScriptでは1つのJavaScriptファイルを1つのモジュールとします。
コードをモジュールに分けることで次のようなメリットがあります。

  • コードの見通しが良くなる
  • 処理を再利用できるようになる
  • 影響範囲が限定されるので保守がしやすい
  • モジュールごとに独立したスコープを持つため、変数名の衝突を防げる

エクスポート例

// 宣言と同時に名前つきエクスポートする
export class Foo { };

インポート例

// 名前つきエクスポートされたfooをインポートする
import { Foo } from "./export.js";

モジュールを使用するには、htmlファイルのscriptタグにtype="module"の記述が必要となります。

<script src="./index.js" type="module"></script>

難しかったこと

  • 非同期処理について、最初に読んだだけではなかなか理解することができませんでした。Promiseasync/awaitにより「非同期処理を実装することができる」という前提で読んでしまっていたため、コードの内容と想像している動きが繋がらず、何が分からないのか分からない状態に陥りました。YouTubeや技術記事で非同期処理を扱っているものを探したり、ChatGPTとの壁打ちを行ったことで、「fetchsetTimeoutのような非同期で行われる処理があり、それをPromiseasync/awaitを使って制御している」ということが分かり、やっとコードの動きを理解することができました。

  • 応用編はどれも難しかったのですが、特にTodoアプリの実装について、コードを理解するのに苦戦しました。フレームワークやライブラリを使わない場合、こんなにコードが複雑になるのかと驚きました。自分でここまで組み立てられるようになるには時間がかかりそうですが、モジュールやクラスを使ってコードを部品に分けて組み合わせる方法を学ぶことができ、とても勉強になりました。

まとめ

JavaScript Primerを読んで、JavaScriptの理解を大きく広げることができました。 まだしっかりと理解できていない部分も多いので、今後のアウトプットと並行しながら何度も読み返し、JavaScriptに慣れていきたいと思います。

Django 環境構築(Docker)

PyCharmとDockerでDjangoの環境構築を行いました。
自分用のメモです。

仮想環境をつくる(PyCharm)

PyCharmで新規プロジェクト→プロジェクトのvenvを選択し、任意のフォルダを作成する
今回は~/Desktop/DjangoBook/mysiteとする

Djangoをインストール

$ pip install django

プロジェクトを作成

$ django-admin startproject config .

Dockerfileを作成

FROM ubuntu:22.04

# Set timezone
ENV TZ=Asia/Tokyo
RUN echo $TZ > /etc/timezone && \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime

# Install required packages
RUN apt update && apt install -y \
    build-essential \
    libncursesw5-dev \
    libssl-dev \
    libsqlite3-dev \
    libgdbm-dev \
    libc6-dev \
    libbz2-dev \
    libffi-dev \
    tk-dev \
    zlib1g-dev \
    wget \
    locales \
    && apt clean && rm -rf /var/lib/apt/lists/*

# Set locale
RUN locale-gen en_US.UTF-8
ENV LANG=en_US.UTF-8 \
    LANGUAGE=en_US.UTF-8 \
    LC_ALL=en_US.UTF-8

# Install Python 3.11
RUN wget https://www.python.org/ftp/python/3.11.4/Python-3.11.4.tgz && \
    tar -zxf Python-3.11.4.tgz && \
    cd Python-3.11.4 && \
    ./configure --enable-optimizations && \
    make altinstall && \
    cd .. && rm -rf Python-3.11.4*

# Set python/pip aliases
RUN update-alternatives --install /usr/local/bin/python3 python3 /usr/local/bin/python3.11 1 && \
    update-alternatives --install /usr/local/bin/pip3 pip3 /usr/local/bin/pip3.11 1

# Upgrade pip
RUN pip3 install --upgrade pip

# Set working directory
WORKDIR /root/mysite
ENV PYTHONUNBUFFERED=1

# Start bash by default
CMD ["/bin/bash"]

requirements.txtを作成

$ pip freeze > requirements.txt

Dockerイメージを作成

$ docker build -t mysite:1.0 .

コンテナを立ち上げる

$ docker run --rm -it -p 8000:8000 \
 -v .:/root/mysite \
--name mysite mysite:1.0 /bin/bash

コンテナ内で必要なPythonパッケージをインストールする

# pip install -r requirements.txt

コンテナ内でブラウザを立ち上げる

# python3 manage.py runserver 0.0.0.0:8000

Django 公式チュートリアルをやってみて

はじめに

現在Djangoの学習に取り組んでおり、最初にUdemyの講座でアプリ開発の流れを学びました。2つ目の教材としてDjango公式チュートリアルに取り組んだので、今回はその感想をまとめました。

👇 Django 公式チュートリアル

docs.djangoproject.com

良かったところ

  • 投票アプリ(Pollアプリ)の作成を通して、テストの書き方やアプリのパッケージ化、管理画面のカスタマイズまで、一連の流れと機能について体系的に学べたのがとても良かったです。
  • チュートリアルの主要な部分が日本語に翻訳されているため、英語が苦手でも取り組みやすいと感じました。
  • アプリを作成するために必要なコードがすべて記載されているので、その通りに手を動かせば実際に動くアプリが作成できるのは、初学者にとってありがたいと思いました。

悪かったところ

全てテキストによる説明のため、処理の流れや構造をイメージしにくいと思いました。初学者がいきなりこのチュートリアルから始めるのは難易度が高そうなので、まずは動画教材などで全体像を掴んでから取り組むのが良いと思います。

学んだこと

チュートリアルに沿ってハンズオンで取り組み、分からないところは都度調べながら進めたことで、Udemyでの学習が終了した時点ではぼんやりとしていたモデル、URL、ビュー、テンプレートの仕組みについて、だいぶ理解を深めることができました。
特に理解を深められたところ、今後気をつけたいことについて以下にまとめました。(コードはチュートリアルより抜粋しています)

リクエスト処理の流れ

ユーザーがサイト上のリンクをクリックし、http://127.0.0.1:8000/polls/1/にリクエストを送ると、まずsettings.pyROOT_URLCONFに設定されているモジュールを参照します。

ROOT_URLCONF = 'mysite.urls'

mysiteディレクトリ内のurls.pyurlpatterns変数を参照します。/polls/1/は一つ目のパスpollsに一致します。第二引数のinclude('polls.urls')は、これまでに一致したURLの部分(polls/)を切り捨て、残りの文字列(1/)をpolls.urlsに渡します。

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]

pollsディレクトリ内のurls.pyを参照し、1/と一致するのは2つ目の"<int:pk>/"なので、対応する DetailViewが呼び出され、ロジック処理などを行ったあとにレスポンスを返します。

from django.urls import path
from . import views

app_name = "polls"
urlpatterns = [
    path("", views.IndexView.as_view(), name="index"),
    path("<int:pk>/", views.DetailView.as_view(), name="detail"),
    path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
    path("<int:question_id>/vote/", views.vote, name="vote"),
]


外部キーによる関連オブジェクトの取得

以下のモデルでは、各Choice(選択肢)が外部キー(ForeignKey)によって一つのQuestion(質問)に関連付けられています。Choiceモデルの一つ目のフィールドであるquestionには、関連したQuestionのオブジェクトが格納されます。

from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField("date published")


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

このとき、choice_set<relatedmodel>_set)という名前を使って、Questionオブジェクトから関連するChoiceオブジェクトを扱うことができます。

from polls.models import Choice, Question

# 主キーが1のQuestionオブジェクトを取得
q = Question.objects.get(pk=1)

# qに関連するChoiceオブジェクトを全て取得
q.choice_set.all()

# qに関連するChoiceオブジェクトの数を取得
q.choice_set.count()

# qに関連するChoiceオブジェクトを新規作成する
q.choice_set.create(choice_text="Not much", votes=0)


レンダーとリダイレクトの違い

レンダー(render())はテンプレートを使って HTML を生成しレスポンスを返すことで、ウェブページを表示します。

from django.shortcuts import render

def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, "polls/results.html", {"question": question})

リダイレクト(redirect())は指定した別のURLに遷移するため、GETリクエストが発生します。
voteメソッド(投票されたら投票数を増やす)はCRUD操作のUpdate(更新)にあたるためPOSTリクエストで呼ばれますが、レンダーを使用すると、ユーザーがページを再読み込みした際に同じPOSTリクエストが再送信される可能性があり、その度に投票数が重複してカウントされてしまいます。これを防ぐために、投票処理が成功した場合はリダイレクト(GETリクエスト)で終了します。

from django.shortcuts import redirect

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST["choice"])
    # 処理が失敗した場合はレンダー
    except (KeyError, Choice.DoesNotExist):
        return render(
            request,
            "polls/detail.html",
            {
                "question": question,
                "error_message": "You didn't select a choice.",
            },
        )
     # 処理が成功した場合はリダイレクト
    else:
        selected_choice.votes = F('votes') + 1
        selected_choice.save()
        return redirect("polls:results", question.id)


汎用ビューのテンプレートとコンテキスト

汎用ビューでは、テンプレート名とコンテキスト変数名がデフォルトで決まっています。

  • テンプレート名:汎用ビューが呼び出されたときに探すテンプレートファイルの名前
  • コンテキスト変数名:テンプレート内でオブジェクトを取得する際に使用する変数名

ListViewでは複数オブジェクトを扱い、DetailViewUpdateViewなどのListView 以外の汎用ビューでは、通常は単一のオブジェクトを扱います。

クラス テンプレート名(デフォルト) コンテキスト変数名(デフォルト) オブジェクト
ListView polls/question_list.html object_list 複数オブジェクトを扱う
ListView 以外(例:DetailView polls/question_detail.html question(モデル名小文字) 単一オブジェクトを扱う(URLに<int:pk>の指定が必要)

テンプレート名とコンテキスト変数名は、以下のように指定することで任意の名前に変更することができます。

役割
使用するテンプレートファイルを明示指定 template_name = "polls/index.html"
テンプレートに渡す変数名を明示指定 context_object_name = "latest_question_list"

難しかったこと

リクエストが送られてから、どのように処理が渡って最終的にレスポンスが返されるのか、またデータの受け渡しがどのように行われているのかを理解するのが難しかったです。一つひとつのコードの流れを追っていくことで少しずつ理解することができましたが、まだ完全には理解しきれていない部分もあるので、今後のアプリ開発を通して実践的に身につけていきたいと思いました。

おわりに

公式チュートリアルに取り組んだことで、Djangoの基本について理解を深めることができました。チュートリアルはなかなかのボリュームだと感じましたが、全体のドキュメントの5%にも満たないそうです。今後、少しずつでもDjangoの豊富な機能を活用できるように、公式ドキュメントを参考にしながら開発を進めていきたいと思います。

Happiness Chain 2025/07の月報(4ヶ月目)

こんにちは、yukikoです!
2025年4月15日にHappiness Chainに入会してから3ヶ月半が経過しました。
7月の振り返りをしていきます。

学習時間(7/1 ~ 7/31)

  • 当月学習時間:208.5h (日平均:6.7h)
  • 累計学習時間:741h

7月も毎日学習を継続することができ、目標学習時間の200hを達成することができました。

学習内容

Python
カレンダー作成、ゴルフスコア判定、自販機問題、ポケモンを題材としたクラスとオブジェクト指向のコーディング課題に取り組みました。特に自販機問題はかなり苦戦しましたが、進めていくうちにオブジェクト指向について少しずつ理解が深まっていくのを感じました。また、提出課題にコードレビューをいただけることで、気を付けるべき部分や構成について学べたのもありがたかったです。
どの課題も最初に見た時は「これ自分にできるのか...?」と思いましたが、やり方を調べながらひとつずつ実装していくことで完成することができ、少し自信をつけることができました。そして書いたコードが思い通りに動いたときは、達成感と楽しさを感じました。今後もたくさん壁に当たると思いますが、諦めずに取り組んでいこうと改めて思いました。

アウトプット記事👇 neigeenfant.hatenablog.com
SQL
動画と書籍2冊で学習し、データモデリングの課題に取り組みました。
「スッキリわかるSQL入門」ではSQLの書き方とデータベースの基本について学習しました。併せて付録の200問超えのSQLドリルに取り組んだことで、手を動かしながらSQLに慣れることができました。
「達人に学ぶDB設計」ではデータベースの論理設計と物理設計について基礎から実践まで学び、正規化やパフォーマンスなど、どのようなことに注意してDB設計を行うべきかを理解することができました。
提出課題ではTwitterのデータモデリング(ER図の作成)を行いました。

アウトプット記事👇 neigeenfant.hatenablog.com neigeenfant.hatenablog.com
REST
Udemyで学習しました。最初は概念的で難しく感じましたが、RESTの原則や特徴、メリットなどを学び、Webアプリケーション開発に広く使われている理由が分かりました。URIの設計やHTTPリクエスト・レスポンスなどについて学ぶことができたので、今後の開発に活かしていきたいと思います。

アウトプット記事👇 neigeenfant.hatenablog.com
Django
Udemyと公式チュートリアルで実際にアプリを作りながら、モデルやビュー、URLなど、Django開発の流れについて学びました。クラスベースビューは少ないコードでCRUD操作の機能を実装でき、フレームワークを使うことで効率的に開発を進められることを実感しました。
公式チュートリアルを一通り読み終えることができたので、8月は復習とアウトプット記事作成から進めていきます。

よかったところ

7月も毎日学習を続けることができました。焦ってロードマップを進めるのではなく、理解に時間をかけるべきところはかけられたかと思います。今後もなるべく腹落ちすることを優先して進めていきたいです。

問題点・改善点

  • 進歩報告会へ1回以上の参加を目標としていましたが朝の睡魔に負けて参加できなかったため、8月は参加できるようにします。
  • 休憩中にスマホを触るとそのまま時間が経ってしまうことが多かったため、勉強中はスマホを遠くに置いて触らないようにします。
  • 一日プラス30分を意識して、できるだけ学習時間を伸ばしていきたいと思います。

8月の目標

  • 学習時間210h以上
  • 進歩報告会に1回以上参加する

まとめ

8月はDjangoでのサイト作成など、より実践的な内容に入っていくので、さらに気合を入れて楽しみながら進めていければと思います。 8月も頑張ります^^