Djangoの基礎

#MTV（モデル・テンプレート・ビュー）概念



##モデル

モデルは、データベースと連携するためのファイル

Djangoでアプリを作ると自動で生成されるmodels.pyがこれに該当します。

一例ですが、models.py　の記述の一例をあげてみます。

```python:models.py
from django.db import models

# Create your models here.

CATEGORY_CHOICES = (
    (1, '握り'),
    (2, '軍艦'),
    (3, '巻き'),
)


class SushiModel(models.Model):
    category = models.IntegerField(choices=CATEGORY_CHOICES)
    name = models.CharField(max_length=50)
```
IDは自動生成されます。categoryやnameがデータベースでのカラム名になります。

##ビュー
views.pyというファイルでDjangoが自動生成してくれるファイルです。
ビューでは、関数ごとにどのHTMLファイルに情報を渡すのか、を指定します。それによりそれぞれの関数をテンプレートに紐付けていくことになります。

##テンプレート
簡単にいうと、HTMLファイル。

**templates**というフォルダの中にhtmlファイル置き、***static***というディレクトリにCSSやjavascriptやイメージファイルを用いて、さらに見栄えをよくしていくということになります。
![1 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/51fd8819-08ae-dae9-5326-2a8067e11ecf.png)

# Djangoプロジェクト作成
仮想環境の構築飛ばしてDjangoのインストールから始めても構いません
## 仮想環境構築
Pythonではvenvという仮想環境を構築するモジュールが標準であります 
```py -m venv (ディレクトリ名)```で仮想環境を構築できます
コマンドプロンプトを開いて仮想環境を作りたいディレクトリまで移動します
移動したらvenvを使用して仮想環境を作成します



```
py -m venv DjangoVenv
```
上のコマンドを打つとDjangoVenvというディレクトリが作成されます
## vscodeでディレクトリを開く
先ほど作成したディレクトリをVScodeで開きます

```
code DjangoVenv
```
これでVScode が開きます。先ほど作成したディレクトリの下にはInclude,Lib,Scripts,pyvenv.cfgが作成されています


```
DjangoVenv
├─Include
├─Lib
├─Scripts
└─pyvenv.cfg
```
## 仮想環境をアクティブにする
WindowsではScriptsディレクトのactivateファイルのpathを入力すると仮想環境がアクティブになります。
なので以下をVScodeのターミナルを開いて入力して下さい

```
\DjangoVenv>Scripts\activate
```
```
(DjangoVenv)\DjangoVenv>
```
(仮想環境のディレクトリ名)が表示されたら成功です

## Djangoのインストール
VScodeのターミナルで以下を入力

```
pip install django
```
以下のように表示されたら成功です。

```
Successfully installed asgiref-3.2.7 django-3.0.6 pytz-2020.1 sqlparse-0.3.1
```
```pip list```でも確認


```
>pip list
Package    Version
---------- -------
asgiref    3.2.7
Django     3.0.6
pip        19.2.3
pytz       2020.1
setuptools 41.2.0
sqlparse   0.3.1
```
Djangoが表示されたら成功です。

## ひな形作成
'''django-admin startproject <プロジェクト名>'''で現在ディレクトリの下に<プロジェクト名>というディレクトリが作成されます


```
django-admin startproject django_practice 
```
と入力するとdjango_practiceディレクトリが作成されます
ディレクトリの中は以下のようになっています

```
📦django_practice
 ┣ 📂django_practice#プロジェクト
 ┃ ┣ 📜asgi.py #asgiというインタフェースの設定ファイル
 ┃ ┣ 📜settings.py　#プロジェクト設定ファイル
 ┃ ┣ 📜urls.py #URLの設定
 ┃ ┣ 📜wsgi.py #wsgiというインタフェースの設定ファイル
 ┃ ┗ 📜__init__.py
 ┗ 📜manage.py
```
## サーバを動かしてみる
manege.pyの引数にrunserverを渡すとサーバ―を動かすことが出来ます


```
python manage.py runserver
```
を入力すると

```
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
May 11, 2020 - 09:24:15
Django version 3.0.6, using settings 'django_practice.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
```
と表示され、デフォルトでhttp://127.0.0.1:8000/ にデプロイされるのでブラウザ開くと以下のページが表示されます
![Django：締め切りのある完璧主義者のためのWebフレームワーク。.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/5d7ab7d6-7800-b6eb-dcd8-80b15764d54e.png)






## アプリケーションの作成  
python manage.py startapp <アプリケーション名>

```
cd django_practice
python manage.py startapp django_application 
```
新しくdjango_applicationというディレクトリが作成されます

## 構造
```
📦django_practice
 ┣ 📂django_application　#アプリケーション
 ┃ ┣ 📂migrations　#データベースの設計図
 ┃ ┣ 📜admin.py　#管理画面設定ファイル
 ┃ ┣ 📜apps.py　#アプリケーション設定ファイル
 ┃ ┣ 📜forms.py **#form形成**
 ┃ ┣ 📜models.py　#データベース定義
 ┃ ┣ 📜tests.py #テスト設定
 ┃ ┣ 📜views.py #ビュー
 ┣ 📂django_practice
 ┃ ┣ 📜asgi.py
 ┃ ┣ 📜settings.py
 ┃ ┣ 📜urls.py
 ┃ ┣ 📜wsgi.py
 ┃ ┗ 📜__init__.py
 ┣ 📜db.sqlite3　#runserverで作成されたデータベース
 ┗ 📜manage.py

```
## ビュー作成¶
django_application/views.py を開いて、以下の Python コードを書いてください
hellofunc関数を定義しします
HttpResponse オブジェクトで返す関数です



```python:views.py
from django.http import HttpResponse


def hellofunc(request):
    html = """
            <!DOCTYPE html>
            <html lang="ja">
            <head>
                <meta charset="UTF-8">
                <title>Django</title>
            </head>
            <body>
                <h1>Hello world</h1>
                <p>こんにちは</p>
            </body>
            </html>
            """
    return HttpResponse(html)
```
## urlの読み込みについて
stratprojectで作成したurls.pyだけでURLパターンを設定していくと設定が多くなり管理しにくいので以下の図のように各アプリケーションごとにurls.pyを作成して管理を分割させます
![2 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/827d8f5c-2332-2b06-c1ff-2f7134f32630.png)

## アプリケーションのurlの連携
まずアプリケーションのディレクトリにurls.pyファイルを作成します。

```
📦django_application
 ┣ 📂migrations
 ┃ ┗ 📜__init__.py
 ┣ 📜admin.py
 ┣ 📜apps.py
 ┣ 📜models.py
 ┣ 📜tests.py
 ┣ 📜urls.py #追加
 ┣ 📜views.py
 ┗ 📜__init__.py
```
今度はアプリケーションのurls.pyをdjango_practice/urls.pyのに読み込ませるため以下を記述します

```python:urls.py

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


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

```
これでアプリケーションのurls.pyを読み込むことが出来ます
## views.pyとurls.pyを使用してサイトに表示

アプリケーションのurls.pyファイルには以下のコードを書いてviewを読み込みpath()関数の引数に関数を入れてください

```python:urls.py
from django.urls import path

from .views import hellofunc
urlpatterns = [
    path('hello/', hellofunc),
]
```
再び````python manage.py runserver```を行いhttp://127.0.0.1:8000/application/hello/ にアクセスすると以下のように表示できます
![127_0_0_1_8000_application_hello_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/52637491-b76d-519d-f484-7d3146d50bfd.png)




## テンプレート使用
今度はテンプレートを使用してサイトに表示させていきます

## テンプレートディレクトリ作成および設定

テンプレートディレクトリをmanage.pyファイルがあるディレクトリに作成します
またテンプレートディレクトリの下にhtmlファイルを作成します
  
```

📦django_practice 
 ┣ 📂django_application
 ┣ 📂django_practice
 ┣ 📂templates #追加
 ┃ ┗ test.html #追加
 ┣ 📜db.sqlite3
 ┗ 📜manage.py

```
htmlファイルは以下のようにしました

```html:test.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>Django</title>
</head>

<body>
    <h1>render_test</h1>
</body>

</html>
```

テンプレートディレクトリの設定をします
settings.pyのTEMPLATESの中のDIRSを以下のように書き変えます

```python:settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')],#書き変え
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
```
この設定をすることでrender()やget_template()、クラスベースビューの内部で設定したディレクトリが呼ばます
## render関数を使用する
renderは簡単に言うとテンプレートをロードした結果を HttpResponse オブジェクトで返す関数です

django_applicationのviews.pyに新しい関数を定義します

```python:views.py
from django.shortcuts import render

def render_test(request):
    return render(request, 'test.html')

```
urls.pyも変更します

```python:urls.py
from django.urls import path

from .views import hellofunc, render_test
urlpatterns = [
    path('hello/', hellofunc),
    path('render/', render_test)
]
```
runseverしてhttp://127.0.0.1:8000/application/render/ アクセスして下さい
![Django.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/6de75606-c35f-02fa-a93f-8bf32bd054bd.png)
### 静的ディレクトリの作成と設定
静的ディレクトリの作成

```
📦django_practice
 ┣ 📂django_application
 ┣ 📂django_practice
 ┣ 📂static　#追加
 ┃ ┗ 📜test.css　#追加
 ┣ 📂templates
 ┣ 📜db.sqlite3
 ┗ 📜manage.py
```
```css:test.css
h1 {
    color: red;
}
```
静的ディレクトリの設定
settings.pyの最後に以下の行を追加

```python:settings.py
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
```
htmlファイルにstaticディレクトリを読み込ませるために以下のように書き変えます

```haml:test.html
<!DOCTYPE html>
<html lang="ja">

<head>
    {% load static %}<!-- staticディレクトリを読み込み-->
    <meta charset="UTF-8">
    <title>Django</title>
    <link rel='stylesheet' type='text/css' href="{% static 'test.css' %}">
</head>

<body>
    <h1>render_test</h1>
</body>

</html>
```
![ジャンゴ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/a2550e6d-8250-8de2-0065-7a52c07f4e3a.png)


## モデルを作成する
django_applicationのmodels.pyを変更してモデルを作成します

```python:models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.CharField(max_length=50)
```
ArticleModelというモデルを作成カラムはtitle,content,reportter
各フィールドは、Field クラスのインスタンスによって表されます たとえば、CharFieldは文字フィールドです
各フィールドが保持するデータのタイプをDjangoに伝えます。

## モデルを有効化する

Djangoの機能からデータベースを作成することが出来ます

## settings.pyファイルのINSTALLED_APPS設定
まずモデルを使用するにはDjngoの設定でアプリケーションをインストールする設定しなければなりません

startappコマンドで作成したアプリを設定に追加します


```python:settings.py
# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_application',  # 追加
] 
```
Djangoにモデルに変更をマイグレーションとして保存します

```
python manage.py makemigrations
```
上を実行すると以下のように出力されます

```
Migrations for 'django_application':
  django_application\migrations\0001_initial.py
    - Create model Article
```
マイグレーションファイルはアプリケーションのmigrationsディレクトリの下に作られます

```
📦django_application
 ┗ 📂migrations
   ┣ 📜0001_initial.py #追加される
   ┗ 📜__init__.py
```

```python:0001_initial.py

from django.db import migrations, models

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Article',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('title', models.CharField(max_length=200)),
                ('content', models.TextField()),
                ('reporter', models.CharField(max_length=50)),
            ],
        ),
    ]
```
次にmigrate実行して、データベースにこれらのモデルテーブルを作成します。

```
 python manage.py migrate
```
以下が表示されたら成功です
```
Applying django_application.0001_initial... OK
```
これでデータベースにテーブルが作成されてモデルが使用できます

## Djangoの管理サイトでモデルの操作
Djangoはモデルの管理サイトは自動で作成されています
そのサイトを利用してモデルの操作を行います

## 管理ユーザーを作成する
まず管理サイトの管理ユーザーを作成する必要があります
以下を実行するとサイトの管理権限を持ったユーザーを作成できます

```

python manage.py createsuperuser
```
好きなユーザー名を入力しEnterを押してください

```
Username: admin
```
希望するemailアドレスを入力
登録しない場合はそのままEnter


```
Email address: admin@example.com
```
パスワードの入力


```
Password: **********
Password (again): *********
Superuser created successfully.
```

これで管理ユーザーが作成されました
次にrunserverを行いhttp://127.0.0.1:8000/admin　にアクセスして下しい

![Log_in_Django_site_admin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/c7004dbb-d2b6-8a39-0401-12a4e35cee85.png)


先ほど作成したユーザーの情報を入力してログインしてください
Django管理インデックスページが表示されます。

![Site_administration_Django_site_admin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/456200e5-049e-8cfb-ff85-9a12d7487896.png)

しかしまだ、今回作成したアプリケーションのモデル管理も場所はないです
ここに追加するにはアプリケーションのadmin.pyを変更する必要があります

```python:admin.py
from .models import Article

admin.site.register(Article)
```
を追記すると管理サイトで表示されるようになります

![Site_administration_Django_site_admin (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457374/8c346992-39e0-581d-9f6f-817e54a36975.png)

これでArticleモデルの管理はこのサイトで行うことが出来ます

## CreateViewで新規データ作成画面を作成

アプリケーションのディレクトリにforms.pyファイルを作成してフォームの型を作ります

```python:forms.py
from django import forms
from .models import Article


class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = '__all__'
```

作成画面のテンプレートを作成

```html:create.html
<!doctype html>
<title>django_practice</title>

<body>
    <form method="post">
        <div>
            {{ form.as_p　}}
            <!-- .as_pで要素ごとにPタグで囲む-->
        </div>
        <button>保存</button> {% csrf_token %}
    </form>
</body>

</html>


```

CreateViewを継承したクラスをviews.pyで作成します

```python:views.py
from django.views.generic import CreateView

from .models import Article
from .forms import ArticleForm
from django.urls import reverse_lazy

class ArticleCreateView(CreateView):
    """
    新規作成
    """
    model = Article
    form_class = ArticleForm
    success_url = reverse_lazy('create')
    template_name = 'create.html'

```
success_url  # データの作成が成したら移動する場所を指定path関数のnameの部分を指定

urls.pyで先ほど作ったクラスを読み込みurlを指定します

```python:urls.py
from django.urls import path

from .views import hellofunc, render_test, ArticleCreateView
urlpatterns = [
    path('hello/', hellofunc),
    path('render/', render_test),
    path('create/', ArticleCreateView.as_view(), name='create'),
]

```

```
📦django_practice
 ┣ 📂django_application
 ┃ ┣ 📜admin.py
 ┃ ┣ 📜apps.py 
 ┃ ┣ 📜forms.py #ArticleForm作成
 ┃ ┣ 📜models.py
 ┃ ┣ 📜tests.py
 ┃ ┣ 📜urls.py　#新しくviewの読み込みurl指定
 ┃ ┣ 📜views.py #ArticleCreateView作成
 ┣ 📂django_practice
 ┣ 📂templates
 ┃ ┣ 📜create.html #ArticleCreateViewで表示するテンプレート作成
 ┃ ┗ 📜test.html
 ┣ 📜db.sqlite3
 ┗ 📜manage.py
```