[{"data":1,"prerenderedAt":1603},["ShallowReactive",2],{"series-laravel_to_django":3},[4],{"id":5,"title":6,"body":7,"category":1586,"createdAt":1588,"description":1589,"extension":1590,"index":114,"meta":1591,"navigation":137,"path":1592,"publish":137,"seo":1593,"series":1594,"seriesTitle":1595,"stem":1596,"tag":1597,"thumbnail":1600,"updatedAt":1601,"__hash__":1602},"series\u002Fseries\u002Flaravel-to-django-1.md","Laravel使いがDjangoでwebアプリを作るよその１：アプリの概要と環境構築",{"type":8,"value":9,"toc":1566},"minimark",[10,14,17,20,33,36,39,42,62,65,68,89,93,101,164,171,176,179,221,224,227,232,582,588,600,614,621,638,661,666,674,689,694,697,700,704,735,738,778,781,792,795,798,802,805,808,819,880,883,940,953,956,959,1034,1051,1054,1067,1351,1354,1372,1375,1382,1388,1395,1401,1411,1419,1430,1449,1456,1466,1469,1520,1527,1556,1559,1562],[11,12,13],"p",{},"こんにちはjunです。最近Laravelでシステムを作る機会が何回かあったので、Laravelによる構築がかなり得意になってきました。しかし会社の方で「pythonを使用した機械学習や統計の機能をwebアプリとして使用できるアプリを開発したい」という企画がでてきました。",[11,15,16],{},"pythonで機械学習や統計の処理（モデル）を作成し、UIやロジックの部分をwebフレームワークで作成します。できたらwebフレームワークの処理部分にて統計ロジックをimportして、データの引き渡しを行いたいと思いました。しかしLaravelはPHPなので連携が難しいです。",[11,18,19],{},"そのため「Python製のwebフレームワークであるdjangoを利用できないか？」と思い、Djangoの勉強をスタートしました。チュートリアルはひとまず終えましたが、Laravelをやっていたおかげで",[21,22,23,27,30],"ul",{},[24,25,26],"li",{},"どんな機能があると便利か？",[24,28,29],{},"Laravelのこの機能がDjangoのこの記述にあたるのか？",[24,31,32],{},"実務上必要となるこの機能を実装するには何を使えばいいのか？",[11,34,35],{},"という視点を用いて学習することができました。このシリーズでは「Laravelを使っていたPHP開発者がDjangoとPythonを使用してアプリを作る」ことを通じてDjangoの学習をしたいと思っています。記事内ではDjangoにおける実装とLaravelにおける実装をリンクしながら解説していきたいと思います。",[11,37,38],{},"利用するDjangoのバージョンは3.2で、Laravelは8とします。第１回のこの記事は環境構築とアプリの概要、Djangoの開発コンセプトやディレクトリ説明がメインとなります。",[11,40,41],{},"なおシリーズでは以下の内容を押さえていることを前提としています",[21,43,44,47,50,53,56,59],{},[24,45,46],{},"Laravelの実務開発経験があるまたは、完成したアプリを作ったことがある。",[24,48,49],{},"Laravelのコンセプトやディレクトリ構成を知っている。",[24,51,52],{},"PythonがPCにインストールされ、基本的な記述を理解している。",[24,54,55],{},"PHPを触ったことが多いが、Pythonはそれほどない。",[24,57,58],{},"Djangoのチュートリアルは行っており、必須の内容は知っている。",[24,60,61],{},"MVCの概念を知っている、使える。",[11,63,64],{},"それでは早速始めていきましょう。",[11,66,67],{},"参考資料",[21,69,70,79,82],{},[24,71,72],{},[73,74,78],"a",{"href":75,"rel":76},"https:\u002F\u002Fdocs.djangoproject.com\u002Fja\u002F3.2",[77],"nofollow","Django ドキュメント3.2",[24,80,81],{},"書籍『現場で使える Django の教科書』",[24,83,84],{},[73,85,88],{"href":86,"rel":87},"https:\u002F\u002Fdocs.docker.jp\u002Fcompose\u002Fdjango.html",[77],"クィックスタート: Compose と Django - Docker ドキュメント",[90,91,92],"h2",{"id":92},"環境構築",[11,94,95,96,100],{},"今回の環境構築はdockerを用いて作成しようと思います。適当なディレクトリ を作成し、",[97,98,99],"code",{},"docker-compose.yaml","とビルドファイルを作成します。",[102,103,108],"pre",{"className":104,"code":105,"language":106,"meta":107,"style":107},"language-bash shiki shiki-themes material-theme-ocean","mkdir laravel_django\ncd laravel_django\n\ntouch Dockerfile\ntouch docker-compose.yaml\nmkdir source\n","bash","",[97,109,110,123,132,139,148,156],{"__ignoreMap":107},[111,112,115,119],"span",{"class":113,"line":114},"line",1,[111,116,118],{"class":117},"s5Dmg","mkdir",[111,120,122],{"class":121},"sfyAc"," laravel_django\n",[111,124,126,130],{"class":113,"line":125},2,[111,127,129],{"class":128},"sdLwU","cd",[111,131,122],{"class":121},[111,133,135],{"class":113,"line":134},3,[111,136,138],{"emptyLinePlaceholder":137},true,"\n",[111,140,142,145],{"class":113,"line":141},4,[111,143,144],{"class":117},"touch",[111,146,147],{"class":121}," Dockerfile\n",[111,149,151,153],{"class":113,"line":150},5,[111,152,144],{"class":117},[111,154,155],{"class":121}," docker-compose.yaml\n",[111,157,159,161],{"class":113,"line":158},6,[111,160,118],{"class":117},[111,162,163],{"class":121}," source\n",[11,165,166,167,170],{},"まずはDockerfileでDjangoが稼働するpythonの環境を作成します。なお、この環境ではApacheやnginxといったwebサーバーとpythonとの連携設定は行わないものとします。コンテナ内で",[97,168,169],{},"run serve","を行います。",[172,173,175],"h3",{"id":174},"dockerfile","Dockerfile",[11,177,178],{},"Dockerfileを以下の様に記述します。",[102,180,183],{"className":181,"code":182,"language":175,"meta":107,"style":107},"language-Dockerfile shiki shiki-themes material-theme-ocean","FROM python:3\nENV PYTHONUNBUFFERED 1\nRUN mkdir \u002Fcode\nWORKDIR \u002Fcode\nADD requirements.txt \u002Fcode\u002F\nRUN pip install -r requirements.txt\nADD . \u002Fcode\u002F\n",[97,184,185,190,195,200,205,210,215],{"__ignoreMap":107},[111,186,187],{"class":113,"line":114},[111,188,189],{},"FROM python:3\n",[111,191,192],{"class":113,"line":125},[111,193,194],{},"ENV PYTHONUNBUFFERED 1\n",[111,196,197],{"class":113,"line":134},[111,198,199],{},"RUN mkdir \u002Fcode\n",[111,201,202],{"class":113,"line":141},[111,203,204],{},"WORKDIR \u002Fcode\n",[111,206,207],{"class":113,"line":150},[111,208,209],{},"ADD requirements.txt \u002Fcode\u002F\n",[111,211,212],{"class":113,"line":158},[111,213,214],{},"RUN pip install -r requirements.txt\n",[111,216,218],{"class":113,"line":217},7,[111,219,220],{},"ADD . \u002Fcode\u002F\n",[11,222,223],{},"python3 イメージをもとにpythonが動く環境を用意します。",[172,225,226],{"id":226},"docker-compose",[11,228,229,231],{},[97,230,99],{},"は以下の様に記述します。",[102,233,237],{"className":234,"code":235,"filename":99,"language":236,"meta":107,"style":107},"language-yaml shiki shiki-themes material-theme-ocean","version: '3'\n\nservices:\n  db:\n    image: mysql:5.7\n    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci\n    environment:\n      MYSQL_DATABASE: preform\n      MYSQL_USER: test\n      MYSQL_PASSWORD: testtest\n      MYSQL_ROOT_PASSWORD: rootroot\n      TZ: Asia\u002FTokyo\n    ports: \n      - \"3306:3306\"\n    volumes: \n      - djangodemo:\u002Fvar\u002Flib\u002Fmysql\n  phpmyadmin:\n    image: phpmyadmin\n    ports:\n      - \"8080:80\"\n    environment:\n     - PMA_ARBITRARY=1\n     - PMA_HOST=db:3306\n     - PMA_USER=root\n     - PMA_PASSWORD=rootroot\n  web:\n    build: .\n    command: python3 manage.py runserver 0.0.0.0:8000\n    volumes:\n      - .\u002Fsource:\u002Fcode\n    ports:\n      - \"8000:8000\"\n    depends_on:\n      - db\nvolumes: \n  djangodemo: {}\n","yaml",[97,238,239,258,262,270,277,287,297,304,315,326,337,348,359,371,386,396,404,412,422,429,441,448,457,465,473,481,489,501,511,518,526,533,545,553,561,571],{"__ignoreMap":107},[111,240,241,245,249,252,255],{"class":113,"line":114},[111,242,244],{"class":243},"s-wAU","version",[111,246,248],{"class":247},"sAklC",":",[111,250,251],{"class":247}," '",[111,253,254],{"class":121},"3",[111,256,257],{"class":247},"'\n",[111,259,260],{"class":113,"line":125},[111,261,138],{"emptyLinePlaceholder":137},[111,263,264,267],{"class":113,"line":134},[111,265,266],{"class":243},"services",[111,268,269],{"class":247},":\n",[111,271,272,275],{"class":113,"line":141},[111,273,274],{"class":243},"  db",[111,276,269],{"class":247},[111,278,279,282,284],{"class":113,"line":150},[111,280,281],{"class":243},"    image",[111,283,248],{"class":247},[111,285,286],{"class":121}," mysql:5.7\n",[111,288,289,292,294],{"class":113,"line":158},[111,290,291],{"class":243},"    command",[111,293,248],{"class":247},[111,295,296],{"class":121}," mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci\n",[111,298,299,302],{"class":113,"line":217},[111,300,301],{"class":243},"    environment",[111,303,269],{"class":247},[111,305,307,310,312],{"class":113,"line":306},8,[111,308,309],{"class":243},"      MYSQL_DATABASE",[111,311,248],{"class":247},[111,313,314],{"class":121}," preform\n",[111,316,318,321,323],{"class":113,"line":317},9,[111,319,320],{"class":243},"      MYSQL_USER",[111,322,248],{"class":247},[111,324,325],{"class":121}," test\n",[111,327,329,332,334],{"class":113,"line":328},10,[111,330,331],{"class":243},"      MYSQL_PASSWORD",[111,333,248],{"class":247},[111,335,336],{"class":121}," testtest\n",[111,338,340,343,345],{"class":113,"line":339},11,[111,341,342],{"class":243},"      MYSQL_ROOT_PASSWORD",[111,344,248],{"class":247},[111,346,347],{"class":121}," rootroot\n",[111,349,351,354,356],{"class":113,"line":350},12,[111,352,353],{"class":243},"      TZ",[111,355,248],{"class":247},[111,357,358],{"class":121}," Asia\u002FTokyo\n",[111,360,362,365,367],{"class":113,"line":361},13,[111,363,364],{"class":243},"    ports",[111,366,248],{"class":247},[111,368,370],{"class":369},"s0W1g"," \n",[111,372,374,377,380,383],{"class":113,"line":373},14,[111,375,376],{"class":247},"      -",[111,378,379],{"class":247}," \"",[111,381,382],{"class":121},"3306:3306",[111,384,385],{"class":247},"\"\n",[111,387,389,392,394],{"class":113,"line":388},15,[111,390,391],{"class":243},"    volumes",[111,393,248],{"class":247},[111,395,370],{"class":369},[111,397,399,401],{"class":113,"line":398},16,[111,400,376],{"class":247},[111,402,403],{"class":121}," djangodemo:\u002Fvar\u002Flib\u002Fmysql\n",[111,405,407,410],{"class":113,"line":406},17,[111,408,409],{"class":243},"  phpmyadmin",[111,411,269],{"class":247},[111,413,415,417,419],{"class":113,"line":414},18,[111,416,281],{"class":243},[111,418,248],{"class":247},[111,420,421],{"class":121}," phpmyadmin\n",[111,423,425,427],{"class":113,"line":424},19,[111,426,364],{"class":243},[111,428,269],{"class":247},[111,430,432,434,436,439],{"class":113,"line":431},20,[111,433,376],{"class":247},[111,435,379],{"class":247},[111,437,438],{"class":121},"8080:80",[111,440,385],{"class":247},[111,442,444,446],{"class":113,"line":443},21,[111,445,301],{"class":243},[111,447,269],{"class":247},[111,449,451,454],{"class":113,"line":450},22,[111,452,453],{"class":247},"     -",[111,455,456],{"class":121}," PMA_ARBITRARY=1\n",[111,458,460,462],{"class":113,"line":459},23,[111,461,453],{"class":247},[111,463,464],{"class":121}," PMA_HOST=db:3306\n",[111,466,468,470],{"class":113,"line":467},24,[111,469,453],{"class":247},[111,471,472],{"class":121}," PMA_USER=root\n",[111,474,476,478],{"class":113,"line":475},25,[111,477,453],{"class":247},[111,479,480],{"class":121}," PMA_PASSWORD=rootroot\n",[111,482,484,487],{"class":113,"line":483},26,[111,485,486],{"class":243},"  web",[111,488,269],{"class":247},[111,490,492,495,497],{"class":113,"line":491},27,[111,493,494],{"class":243},"    build",[111,496,248],{"class":247},[111,498,500],{"class":499},"sx098"," .\n",[111,502,504,506,508],{"class":113,"line":503},28,[111,505,291],{"class":243},[111,507,248],{"class":247},[111,509,510],{"class":121}," python3 manage.py runserver 0.0.0.0:8000\n",[111,512,514,516],{"class":113,"line":513},29,[111,515,391],{"class":243},[111,517,269],{"class":247},[111,519,521,523],{"class":113,"line":520},30,[111,522,376],{"class":247},[111,524,525],{"class":121}," .\u002Fsource:\u002Fcode\n",[111,527,529,531],{"class":113,"line":528},31,[111,530,364],{"class":243},[111,532,269],{"class":247},[111,534,536,538,540,543],{"class":113,"line":535},32,[111,537,376],{"class":247},[111,539,379],{"class":247},[111,541,542],{"class":121},"8000:8000",[111,544,385],{"class":247},[111,546,548,551],{"class":113,"line":547},33,[111,549,550],{"class":243},"    depends_on",[111,552,269],{"class":247},[111,554,556,558],{"class":113,"line":555},34,[111,557,376],{"class":247},[111,559,560],{"class":121}," db\n",[111,562,564,567,569],{"class":113,"line":563},35,[111,565,566],{"class":243},"volumes",[111,568,248],{"class":247},[111,570,370],{"class":369},[111,572,574,577,579],{"class":113,"line":573},36,[111,575,576],{"class":243},"  djangodemo",[111,578,248],{"class":247},[111,580,581],{"class":247}," {}\n",[11,583,584,587],{},[97,585,586],{},"db","ではデータベースを定義しています。DjangoはSQLiteを使用した簡易的なDBが用意されています。ただし実務ではmysqlなどのDBサーバーを使用することが多いので、今回はmysqlを使用できる様にします。",[589,590,594,595],"div",{"className":591},[592,593],"alert","alert-info","\nDjangoでmysqlを使用するためにはpythonモジュールのmysqlclientが必要です。この環境にはデフォルトでないので注意してください。他のDBサーバーを使用する場合は適宜ドライバをインストールしてください。\n",[73,596,599],{"target":597,"href":598},"_blank","https:\u002F\u002Fdocs.djangoproject.com\u002Fja\u002F3.2\u002Ftopics\u002Finstall\u002F#get-your-database-running","本家ドキュメントを参照",[11,601,602,603,606,607,609,610,613],{},"DB内部をすぐに確認できる様にphpmyadminを入れておきます。（好みなのでなくてもいいです。）\nそして",[97,604,605],{},"web","では同階層にある",[97,608,175],{},"をビルドして実行できる様になります。立ち上げ時に",[97,611,612],{},"python3 manage.py runserver 0.0.0.0:8000","をしてwebサーバを立ち上げる設定にしています。",[11,615,616,617,620],{},"このコンテナを起動する前に ",[97,618,619],{},"requirements.txt"," をDockerfileと同じ階層に生成しておき、以下の内容を記述します。",[102,622,626],{"className":623,"code":624,"filename":619,"language":625,"meta":107,"style":107},"language-txt shiki shiki-themes material-theme-ocean","Django==3.2\nmysqlclient==2.1.0\n","txt",[97,627,628,633],{"__ignoreMap":107},[111,629,630],{"class":113,"line":114},[111,631,632],{},"Django==3.2\n",[111,634,635],{"class":113,"line":125},[111,636,637],{},"mysqlclient==2.1.0\n",[11,639,640,642,643,646,647,650,651,653,654,656,657,660],{},[97,641,619],{}," はpythonライブラリ管理ツールpipの設定ファイルです。npmの",[97,644,645],{},"package.json","やcomposerの",[97,648,649],{},"composer.json","といったものと同じです。pythonのモジュール管理はpipを使用することが多く、",[97,652,619],{}," は環境ないの依存するモジュールとそのバージョンを記述して配置しておきます。そして",[97,655,619],{}," がある階層で ",[97,658,659],{},"pip install","をすることで自動的に依存関係をインストールしてくれます。Django3.2とmysqlclientを記述しておきます。",[11,662,663,665],{},[97,664,619],{},"を記述したら以下のコマンドを実行してDjangoのソースを作成します。",[102,667,672],{"className":668,"code":670,"language":671},[669],"language-text","docker-compose run web django-admin.py startproject djangodemo .\n","text",[97,673,670],{"__ignoreMap":107},[11,675,676,677,680,681,684,685,688],{},"すると",[97,678,679],{},"source\u002F","配下にDjangoのソースが生成されるはずです。\nそして準備が整ったら",[97,682,683],{},"docker-compose up -d --build"," を行って構築を行います。問題なくいった場合はブラウザにて ",[97,686,687],{},"localhost:8000"," を閲覧すると、Djangoのウェルカムページが表示されるはずです。",[690,691],"image-render",{":src":692,":width":693},"'laralve_to_django\u002Fwelcome.png'","'100%'",[90,695,696],{"id":696},"アプリ概要",[11,698,699],{},"今回作成するアプリはn○teみたいなブログサービスを作成しようと思います。",[701,702,703],"h4",{"id":703},"ユーザー系の特徴",[21,705,706,709,712,715,718,721],{},[24,707,708],{},"利用する際にはユーザーとしてアカウントを作る（今回は全てゲストとする）。",[24,710,711],{},"ログインはアドレスとパスワードを使用する。",[24,713,714],{},"アプリを利用する一般ユーザーと管理を行う管理ユーザーが存在する。",[24,716,717],{},"管理ユーザーは特定の管理用ルートから入る。",[24,719,720],{},"退会可能。退会時は関連するデータは削除される。",[24,722,723,724],{},"プロフィールでは以下の項目を持つ\n",[21,725,726,729,732],{},[24,727,728],{},"ユーザー名（仮名）",[24,730,731],{},"プロフィール文",[24,733,734],{},"アバター写真",[701,736,737],{"id":737},"ブログ機能",[21,739,740,743,760,763,766,769,772,775],{},[24,741,742],{},"ブログを作成することができ、公開することができる。",[24,744,745,746],{},"ブログは以下の項目を持つ\n",[21,747,748,751,754,757],{},[24,749,750],{},"タイトル",[24,752,753],{},"内容（リッチテキスト）",[24,755,756],{},"タグ（任意）",[24,758,759],{},"公開日時",[24,761,762],{},"下書きとして保存することができる。更新時も下書き可能。",[24,764,765],{},"任意数のタグを添付できる。タグはユーザーが新しく作成できる。",[24,767,768],{},"削除可能",[24,770,771],{},"画像の添付が可能。",[24,773,774],{},"アップロードした画像は管理できる。",[24,776,777],{},"公開側からコメント可能",[701,779,780],{"id":780},"一覧検索機能",[21,782,783,786,789],{},[24,784,785],{},"サイトトップは投稿された記事が新着順に並ぶ。",[24,787,788],{},"任意のタグを選んで一覧表示することが可能。",[24,790,791],{},"部分一致検索も一応可能とする。",[11,793,794],{},"一通りユーザーエンティティから、記事のCURD、リレーションの練習はできると思います。すべてのビューはpython側でレンダリングを行い、Vue.jsなどは今回使用しません。違う機会にrest apiを使用した構成を作ってみたいとおおいます。",[11,796,797],{},"デザインに関してはいつものbootstrapを使用します。",[90,799,801],{"id":800},"djangoの大まかな解説","Djangoの大まかな解説",[11,803,804],{},"詳細なロジックなどは次の記事で解説したいと思います。今回はDjangoのディレクトリ構成やLaravelと似ているとこやリンクしている中核的な機能を解説したいと思います。",[172,806,807],{"id":807},"コマンドによる制御",[11,809,810,811,814,815,818],{},"Laravelでは ",[97,812,813],{},"php artisan"," を使用することでコントローラーを作ったり、マイグレーションを実行したりできます。Djangoにも似た様なものがあります。使用する時はソーストップの ",[97,816,817],{},"manage.py"," がある箇所で実行します。例えば以下の様な機能があります。",[102,820,822],{"className":104,"code":821,"language":106,"meta":107,"style":107},"# 簡易webサーバーを起動\npython3 manage.py runserve\n\n# マイグレーションを実行\npython3 manage.py migrate\n\n# アプリのテンプレートを作成\npython3 manage.py startapp APP_NAME\n\n",[97,823,824,830,841,845,850,859,863,868],{"__ignoreMap":107},[111,825,826],{"class":113,"line":114},[111,827,829],{"class":828},"sC9rS","# 簡易webサーバーを起動\n",[111,831,832,835,838],{"class":113,"line":125},[111,833,834],{"class":117},"python3",[111,836,837],{"class":121}," manage.py",[111,839,840],{"class":121}," runserve\n",[111,842,843],{"class":113,"line":134},[111,844,138],{"emptyLinePlaceholder":137},[111,846,847],{"class":113,"line":141},[111,848,849],{"class":828},"# マイグレーションを実行\n",[111,851,852,854,856],{"class":113,"line":150},[111,853,834],{"class":117},[111,855,837],{"class":121},[111,857,858],{"class":121}," migrate\n",[111,860,861],{"class":113,"line":158},[111,862,138],{"emptyLinePlaceholder":137},[111,864,865],{"class":113,"line":217},[111,866,867],{"class":828},"# アプリのテンプレートを作成\n",[111,869,870,872,874,877],{"class":113,"line":306},[111,871,834],{"class":117},[111,873,837],{"class":121},[111,875,876],{"class":121}," startapp",[111,878,879],{"class":121}," APP_NAME\n",[11,881,882],{},"Laravelで例えると",[102,884,886],{"className":104,"code":885,"language":106,"meta":107,"style":107},"# 簡易webサーバーを起動\nphp artisan serve\n\n# マイグレーションを実行\nphp artisan migrate\n\n# コントローラーのテンプレートを作成\nphp artisan make:controller CONTROLLER_NAME\n\n",[97,887,888,892,903,907,911,919,923,928],{"__ignoreMap":107},[111,889,890],{"class":113,"line":114},[111,891,829],{"class":828},[111,893,894,897,900],{"class":113,"line":125},[111,895,896],{"class":117},"php",[111,898,899],{"class":121}," artisan",[111,901,902],{"class":121}," serve\n",[111,904,905],{"class":113,"line":134},[111,906,138],{"emptyLinePlaceholder":137},[111,908,909],{"class":113,"line":141},[111,910,849],{"class":828},[111,912,913,915,917],{"class":113,"line":150},[111,914,896],{"class":117},[111,916,899],{"class":121},[111,918,858],{"class":121},[111,920,921],{"class":113,"line":158},[111,922,138],{"emptyLinePlaceholder":137},[111,924,925],{"class":113,"line":217},[111,926,927],{"class":828},"# コントローラーのテンプレートを作成\n",[111,929,930,932,934,937],{"class":113,"line":306},[111,931,896],{"class":117},[111,933,899],{"class":121},[111,935,936],{"class":121}," make:controller",[111,938,939],{"class":121}," CONTROLLER_NAME\n",[11,941,942,943,946,947,952],{},"以上の様になります。この ",[97,944,945],{},"python3 manage.py","で実行できる内容は",[73,948,951],{"href":949,"rel":950},"https:\u002F\u002Fdocs.djangoproject.com\u002Fja\u002F3.2\u002Fref\u002Fdjango-admin\u002F",[77],"こちらのドキュメント","で知ることができます。",[172,954,955],{"id":955},"ディレクトリとファイルの構成",[11,957,958],{},"初期のファイル構成は以下の様になっています。",[102,960,962],{"className":104,"code":961,"language":106,"meta":107,"style":107},"├── db.sqlite3\n├── djangodemo\n│   ├── __init__.py\n│   ├── asgi.py\n│   ├── settings.py\n│   ├── urls.py\n│   └── wsgi.py\n├── manage.py\n",[97,963,964,972,979,990,999,1008,1017,1027],{"__ignoreMap":107},[111,965,966,969],{"class":113,"line":114},[111,967,968],{"class":117},"├──",[111,970,971],{"class":121}," db.sqlite3\n",[111,973,974,976],{"class":113,"line":125},[111,975,968],{"class":117},[111,977,978],{"class":121}," djangodemo\n",[111,980,981,984,987],{"class":113,"line":134},[111,982,983],{"class":117},"│",[111,985,986],{"class":121},"   ├──",[111,988,989],{"class":121}," __init__.py\n",[111,991,992,994,996],{"class":113,"line":141},[111,993,983],{"class":117},[111,995,986],{"class":121},[111,997,998],{"class":121}," asgi.py\n",[111,1000,1001,1003,1005],{"class":113,"line":150},[111,1002,983],{"class":117},[111,1004,986],{"class":121},[111,1006,1007],{"class":121}," settings.py\n",[111,1009,1010,1012,1014],{"class":113,"line":158},[111,1011,983],{"class":117},[111,1013,986],{"class":121},[111,1015,1016],{"class":121}," urls.py\n",[111,1018,1019,1021,1024],{"class":113,"line":217},[111,1020,983],{"class":117},[111,1022,1023],{"class":121},"   └──",[111,1025,1026],{"class":121}," wsgi.py\n",[111,1028,1029,1031],{"class":113,"line":306},[111,1030,968],{"class":117},[111,1032,1033],{"class":121}," manage.py\n",[11,1035,1036,1039,1040,1042,1043,1046,1047,1050],{},[97,1037,1038],{},"djangodemo\u002F"," はDjangoのアプリを最初に作成した時に生成されるディレクトリです。",[97,1041,1038],{}," では特に ",[97,1044,1045],{},"settings.py","と",[97,1048,1049],{},"urls.py","が重要です。",[701,1052,1053],{"id":1053},"設定ファイル",[11,1055,1056,1058,1059,1062,1063,1066],{},[97,1057,1045],{}," はLaravelでいう",[97,1060,1061],{},"config\u002F","ディレクトリ配下のファイルたちを一つにまとめた様なものになっています。特に",[97,1064,1065],{},"config\u002Fapp.php","の記述が近いかもしれません。一部抜粋して解説します。",[102,1068,1072],{"className":1069,"code":1070,"filename":1045,"language":1071,"meta":107,"style":107},"language-python shiki shiki-themes material-theme-ocean","BASE_DIR = Path(__file__).resolve().parent.parent\n\nSECRET_KEY = 'hogehoge'\n\n# SECURITY WARNING: don't run with debug turned on in production!\n# Laravelのapp.debugと同じ\nDEBUG = True\n\n# Application definition\n# Djangoが利用可能なアプリ（モジュール）Laravelにはないかも。\nINSTALLED_APPS = [\n    'django.contrib.admin',\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.messages',\n    'django.contrib.staticfiles',\n]\n\n# laravel の app\u002FHttp\u002FKernel.php のmiddlewareみたいなもの\nMIDDLEWARE = [\n    'django.middleware.security.SecurityMiddleware',\n    'django.contrib.sessions.middleware.SessionMiddleware',\n    'django.middleware.common.CommonMiddleware',\n    'django.middleware.csrf.CsrfViewMiddleware',\n    'django.contrib.auth.middleware.AuthenticationMiddleware',\n    'django.contrib.messages.middleware.MessageMiddleware',\n    'django.middleware.clickjacking.XFrameOptionsMiddleware',\n]\n\n# Laravelのroutesみたいなもの。\nROOT_URLCONF = 'djangodemo.urls'\n\n# Laravelのビューテンプレートが resource\u002Fviewであることを決めている様なことと同じ。DjangoないのTemplateの読み込み先を定義している\nTEMPLATES = [\n    # ...\n]\n\nWSGI_APPLICATION = 'djangodemo.wsgi.application'\n\n# Laravelのconfig\u002Fdatabase.phpと同じ。使用するDBドライバやアクセス情報を記述。\nDATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.mysql',\n        'NAME': 'preform',\n        'USER': 'root',\n        'PASSWORD': 'rootroot',\n        'HOST': 'db',\n        'PORT': '3306',\n    }\n}\n\n# 静的ファイルを配置する箇所。Laravelのstorageディレクトリ を定義している様なもの。\nSTATIC_URL = '\u002Fstatic\u002F'\n\n","python",[97,1073,1074,1079,1083,1088,1092,1097,1102,1107,1111,1116,1121,1126,1131,1136,1141,1146,1151,1156,1161,1165,1170,1175,1180,1185,1190,1195,1200,1205,1210,1214,1218,1223,1228,1232,1237,1242,1247,1252,1257,1263,1268,1274,1280,1286,1292,1298,1304,1310,1316,1322,1328,1334,1339,1345],{"__ignoreMap":107},[111,1075,1076],{"class":113,"line":114},[111,1077,1078],{},"BASE_DIR = Path(__file__).resolve().parent.parent\n",[111,1080,1081],{"class":113,"line":125},[111,1082,138],{"emptyLinePlaceholder":137},[111,1084,1085],{"class":113,"line":134},[111,1086,1087],{},"SECRET_KEY = 'hogehoge'\n",[111,1089,1090],{"class":113,"line":141},[111,1091,138],{"emptyLinePlaceholder":137},[111,1093,1094],{"class":113,"line":150},[111,1095,1096],{},"# SECURITY WARNING: don't run with debug turned on in production!\n",[111,1098,1099],{"class":113,"line":158},[111,1100,1101],{},"# Laravelのapp.debugと同じ\n",[111,1103,1104],{"class":113,"line":217},[111,1105,1106],{},"DEBUG = True\n",[111,1108,1109],{"class":113,"line":306},[111,1110,138],{"emptyLinePlaceholder":137},[111,1112,1113],{"class":113,"line":317},[111,1114,1115],{},"# Application definition\n",[111,1117,1118],{"class":113,"line":328},[111,1119,1120],{},"# Djangoが利用可能なアプリ（モジュール）Laravelにはないかも。\n",[111,1122,1123],{"class":113,"line":339},[111,1124,1125],{},"INSTALLED_APPS = [\n",[111,1127,1128],{"class":113,"line":350},[111,1129,1130],{},"    'django.contrib.admin',\n",[111,1132,1133],{"class":113,"line":361},[111,1134,1135],{},"    'django.contrib.auth',\n",[111,1137,1138],{"class":113,"line":373},[111,1139,1140],{},"    'django.contrib.contenttypes',\n",[111,1142,1143],{"class":113,"line":388},[111,1144,1145],{},"    'django.contrib.sessions',\n",[111,1147,1148],{"class":113,"line":398},[111,1149,1150],{},"    'django.contrib.messages',\n",[111,1152,1153],{"class":113,"line":406},[111,1154,1155],{},"    'django.contrib.staticfiles',\n",[111,1157,1158],{"class":113,"line":414},[111,1159,1160],{},"]\n",[111,1162,1163],{"class":113,"line":424},[111,1164,138],{"emptyLinePlaceholder":137},[111,1166,1167],{"class":113,"line":431},[111,1168,1169],{},"# laravel の app\u002FHttp\u002FKernel.php のmiddlewareみたいなもの\n",[111,1171,1172],{"class":113,"line":443},[111,1173,1174],{},"MIDDLEWARE = [\n",[111,1176,1177],{"class":113,"line":450},[111,1178,1179],{},"    'django.middleware.security.SecurityMiddleware',\n",[111,1181,1182],{"class":113,"line":459},[111,1183,1184],{},"    'django.contrib.sessions.middleware.SessionMiddleware',\n",[111,1186,1187],{"class":113,"line":467},[111,1188,1189],{},"    'django.middleware.common.CommonMiddleware',\n",[111,1191,1192],{"class":113,"line":475},[111,1193,1194],{},"    'django.middleware.csrf.CsrfViewMiddleware',\n",[111,1196,1197],{"class":113,"line":483},[111,1198,1199],{},"    'django.contrib.auth.middleware.AuthenticationMiddleware',\n",[111,1201,1202],{"class":113,"line":491},[111,1203,1204],{},"    'django.contrib.messages.middleware.MessageMiddleware',\n",[111,1206,1207],{"class":113,"line":503},[111,1208,1209],{},"    'django.middleware.clickjacking.XFrameOptionsMiddleware',\n",[111,1211,1212],{"class":113,"line":513},[111,1213,1160],{},[111,1215,1216],{"class":113,"line":520},[111,1217,138],{"emptyLinePlaceholder":137},[111,1219,1220],{"class":113,"line":528},[111,1221,1222],{},"# Laravelのroutesみたいなもの。\n",[111,1224,1225],{"class":113,"line":535},[111,1226,1227],{},"ROOT_URLCONF = 'djangodemo.urls'\n",[111,1229,1230],{"class":113,"line":547},[111,1231,138],{"emptyLinePlaceholder":137},[111,1233,1234],{"class":113,"line":555},[111,1235,1236],{},"# Laravelのビューテンプレートが resource\u002Fviewであることを決めている様なことと同じ。DjangoないのTemplateの読み込み先を定義している\n",[111,1238,1239],{"class":113,"line":563},[111,1240,1241],{},"TEMPLATES = [\n",[111,1243,1244],{"class":113,"line":573},[111,1245,1246],{},"    # ...\n",[111,1248,1250],{"class":113,"line":1249},37,[111,1251,1160],{},[111,1253,1255],{"class":113,"line":1254},38,[111,1256,138],{"emptyLinePlaceholder":137},[111,1258,1260],{"class":113,"line":1259},39,[111,1261,1262],{},"WSGI_APPLICATION = 'djangodemo.wsgi.application'\n",[111,1264,1266],{"class":113,"line":1265},40,[111,1267,138],{"emptyLinePlaceholder":137},[111,1269,1271],{"class":113,"line":1270},41,[111,1272,1273],{},"# Laravelのconfig\u002Fdatabase.phpと同じ。使用するDBドライバやアクセス情報を記述。\n",[111,1275,1277],{"class":113,"line":1276},42,[111,1278,1279],{},"DATABASES = {\n",[111,1281,1283],{"class":113,"line":1282},43,[111,1284,1285],{},"    'default': {\n",[111,1287,1289],{"class":113,"line":1288},44,[111,1290,1291],{},"        'ENGINE': 'django.db.backends.mysql',\n",[111,1293,1295],{"class":113,"line":1294},45,[111,1296,1297],{},"        'NAME': 'preform',\n",[111,1299,1301],{"class":113,"line":1300},46,[111,1302,1303],{},"        'USER': 'root',\n",[111,1305,1307],{"class":113,"line":1306},47,[111,1308,1309],{},"        'PASSWORD': 'rootroot',\n",[111,1311,1313],{"class":113,"line":1312},48,[111,1314,1315],{},"        'HOST': 'db',\n",[111,1317,1319],{"class":113,"line":1318},49,[111,1320,1321],{},"        'PORT': '3306',\n",[111,1323,1325],{"class":113,"line":1324},50,[111,1326,1327],{},"    }\n",[111,1329,1331],{"class":113,"line":1330},51,[111,1332,1333],{},"}\n",[111,1335,1337],{"class":113,"line":1336},52,[111,1338,138],{"emptyLinePlaceholder":137},[111,1340,1342],{"class":113,"line":1341},53,[111,1343,1344],{},"# 静的ファイルを配置する箇所。Laravelのstorageディレクトリ を定義している様なもの。\n",[111,1346,1348],{"class":113,"line":1347},54,[111,1349,1350],{},"STATIC_URL = '\u002Fstatic\u002F'\n",[701,1352,1353],{"id":1353},"ルーティング",[11,1355,1356,1357,1359,1360,1363,1364,1367,1368,1371],{},"次は",[97,1358,1049],{},"です。これはLaravelでいうところの ",[97,1361,1362],{},"routes\u002F","と内容的には一緒です。ここでHTTPリクエストに対する処理を結びつけています。Urlディスパッチャと言われています。Laravelでは",[97,1365,1366],{},"web.php","や",[97,1369,1370],{},"api.php","などいくらか分かれていますが、Djangoではデフォルトで一つです。詳細な記述は次回説明します。",[701,1373,1374],{"id":1374},"アプリ側のディレクトリ",[11,1376,1377,1378,1381],{},"次にアプリを作成します。Djangoは機能ごとにディレクトリを分割しアプリ(app)と呼んでいます。例としてユーザーのアカウント設定や認証を行う機能を作成するために、",[97,1379,1380],{},"account","というアプリを作成します。",[102,1383,1386],{"className":1384,"code":1385,"language":671},[669],"python3 manage.py startapp account\n",[97,1387,1385],{"__ignoreMap":107},[11,1389,1390,1391,1394],{},"ディレクトリ が一つ増えて、",[97,1392,1393],{},"account\u002F","というのが作成されたはずです。アプリ内には初期では以下の通りテンプレートが作成されます。",[102,1396,1399],{"className":1397,"code":1398,"language":671},[669],"├── account\n│   ├── __init__.py\n│   ├── admin.py\n│   ├── apps.py\n│   ├── migrations\n│   │   └── __init__.py\n│   ├── models.py\n│   ├── tests.py\n│   └── views.py\n├── db.sqlite3\n├── djangodemo\n├── manage.py\n",[97,1400,1398],{"__ignoreMap":107},[11,1402,1403,1404,1407,1408,1410],{},"Laravelは",[97,1405,1406],{},"app\u002F","配下にコントローラーやモデル、ジョブなどのクラスファイルを定義します。独立した機能であっても",[97,1409,1406],{},"配下に配置してクラス名などで判別する感じです。",[11,1412,1413,1414,1418],{},"しかしDjangoは",[1415,1416,1417],"strong",{},"機能ごとにディレクトリ を作成し、その機能に関連するモデル、ビュー、テストの設定を記述","します。ここがLaravelとすこし違うところです。",[11,1420,1421,1422,1425,1426,1429],{},"アプリを",[97,1423,1424],{},"setting.py","の",[97,1427,1428],{},"INSTALLED_APPS","に記述することで、",[102,1431,1433],{"className":1069,"code":1432,"language":1071,"meta":107,"style":107},"from account.model import Account\n\n# account\u002Fmodel.py のAccountクラスを使用する\n",[97,1434,1435,1440,1444],{"__ignoreMap":107},[111,1436,1437],{"class":113,"line":114},[111,1438,1439],{},"from account.model import Account\n",[111,1441,1442],{"class":113,"line":125},[111,1443,138],{"emptyLinePlaceholder":137},[111,1445,1446],{"class":113,"line":134},[111,1447,1448],{},"# account\u002Fmodel.py のAccountクラスを使用する\n",[11,1450,1451,1452,1455],{},"などそのアプリ内機能をモジュールとして使用できます。Laravel（PHP）風に解説すると、適切な名前空間を定義して任意のファイルで",[97,1453,1454],{},"use","する感じです。",[102,1457,1460],{"className":1458,"code":1459,"language":896,"meta":107,"style":107},"language-php shiki shiki-themes material-theme-ocean","use App\\Models\\Account\n",[97,1461,1462],{"__ignoreMap":107},[111,1463,1464],{"class":113,"line":114},[111,1465,1459],{},[11,1467,1468],{},"それぞれのファイルを説明します。",[21,1470,1471,1477,1486,1495,1504,1510],{},[24,1472,1473,1476],{},[97,1474,1475],{},"admin.py",":Djangoが提供する管理者画面でモデルの内容をどう表記するかを定義します。",[24,1478,1479,1482,1483,1485],{},[97,1480,1481],{},"apps.py",":アプリの設定ファイル。アプリの名前やデフォルトのプライマリーキーなどを設定でき、",[97,1484,1428],{},"に必要",[24,1487,1488,1491,1492],{},[97,1489,1490],{},"models.py",": アプリのモデルファイル。テーブルや使用するフィールドの定義などを行う。Laravelでいう",[97,1493,1494],{},"app\u002Fmodels",[24,1496,1497,1500,1501],{},[97,1498,1499],{},"tets.py",": アプリのテストファイル。テストコードを記述する。Laravelでいう",[97,1502,1503],{},"tests\u002F",[24,1505,1506,1509],{},[97,1507,1508],{},"views.py",": アプリのビューファイル。DjangoではビューはLaravelでいうControllerみたいな働きをする。",[24,1511,1512,1515,1516,1519],{},[97,1513,1514],{},"migrations\u002F",": DBに対する変更、マイグレーションファイルが格納されます。Laravelでいう、",[97,1517,1518],{},"database\u002Fmigrations","です。",[11,1521,1522,1523,1526],{},"のこっている ",[97,1524,1525],{},"__init__.py","ですがこれはpythonがディレクトリ をパッケージとして認識して、importできる様にするために必要なファイルです。python2ではこのファイルがないとimportが動作しません。python3からは不要ですが、後方互換性のために作っておいて損はありません。",[102,1528,1530],{"className":1069,"code":1529,"language":1071,"meta":107,"style":107},"from account.models\n\"\"\"\naccountディレクトリ（パッケージ）のmodels.py（モジュール）を読み込むということが,\n__init__.pyがあるとできる。\n\"\"\"\n",[97,1531,1532,1537,1542,1547,1552],{"__ignoreMap":107},[111,1533,1534],{"class":113,"line":114},[111,1535,1536],{},"from account.models\n",[111,1538,1539],{"class":113,"line":125},[111,1540,1541],{},"\"\"\"\n",[111,1543,1544],{"class":113,"line":134},[111,1545,1546],{},"accountディレクトリ（パッケージ）のmodels.py（モジュール）を読み込むということが,\n",[111,1548,1549],{"class":113,"line":141},[111,1550,1551],{},"__init__.pyがあるとできる。\n",[111,1553,1554],{"class":113,"line":150},[111,1555,1541],{},[90,1557,1558],{"id":1558},"今回はとりあえずここまで",[11,1560,1561],{},"ひとまずこの回ではディレクトリやファイルの説明までとしておきます。次回はユーザーモデルを使用した認証の実装とLaravelと比較したCRUDの一部（記事の作成）を実装します。",[1563,1564,1565],"style",{},"html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}",{"title":107,"searchDepth":134,"depth":134,"links":1567},[1568,1572,1577,1585],{"id":92,"depth":125,"text":92,"children":1569},[1570,1571],{"id":174,"depth":134,"text":175},{"id":226,"depth":134,"text":226},{"id":696,"depth":125,"text":696,"children":1573},[1574,1575,1576],{"id":703,"depth":141,"text":703},{"id":737,"depth":141,"text":737},{"id":780,"depth":141,"text":780},{"id":800,"depth":125,"text":801,"children":1578},[1579,1580],{"id":807,"depth":134,"text":807},{"id":955,"depth":134,"text":955,"children":1581},[1582,1583,1584],{"id":1053,"depth":141,"text":1053},{"id":1353,"depth":141,"text":1353},{"id":1374,"depth":141,"text":1374},{"id":1558,"depth":125,"text":1558},[1587],"devstack","2022-02-12","アプリの解説とシリーズの概要","md",{},"\u002Fseries\u002Flaravel-to-django-1",{"title":6,"description":1589},"laravel_to_django","Laravel使いがDjangoでwebアプリを作るよ","series\u002Flaravel-to-django-1",[1598,1071,1599,896],"django","laravel","laralve_to_django\u002Fthumbnail.png",null,"k4TYlI4xXfHM5YMh4HtklCzEfD1cyqgLf2FCDeypoBY",1780987151372]