Django - Qiita上のtutorial appを概観し、機能をプラスする（１）

##1年ほど前に書いた記事です。
Publicに公開できるようにQiitaに投稿いたします。

## はじめに

この記事では
 - Djangoアプリケーションのそれぞれのファイルの相関と大まかな役割を理解できる
 - 既存のアプリケーションを概観し、適切な変更を加えられるようになる
 - Djangoを知らない人には、ほう、そんな感じか、というイメージを持ってもらえる

ことが目的です。個人的には復習のつもりで取り組みます。

以下の記事のアプリを概観し、
[[Python] Djangoチュートリアル - 汎用業務Webアプリを最速で作る](https://qiita.com/okoppe8/items/54eb105c9c94c0960f14#%E6%89%8B%E9%A0%86%EF%BC%93%E3%83%A2%E3%83%87%E3%83%AB%E4%BD%9C%E6%88%90)

今回は、
**ログイン機能とその画面の作成(2)と
画像ファイルのアップロード・表示を可能にする(1)作業を行います。**

以下は今回の(1)の作業を終えたもの
https://github.com/Rio157/crud-image-app.git



## 開発環境

- Windows10
- Ubuntu LTS18.04 - Windows for Linux Terminal
- Visual Studio Code にてUbuntuを開いています。

## 完成型
![93f06bcd-4570-4d5c-ab3d-5d14c993de7f-1920x910r.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515538/d756b452-931f-1aa5-3904-836eafc64268.png)
アイテムの一覧画面


![7eb35643-b63b-4d38-8557-272241099b27-1920x912r.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515538/503eadec-648d-92c7-a542-258535298e6b.png)
アイテムの詳細画面




## 機能
今回は画像のアップロードと一覧画面、詳細画面にてアップロードされた画像の表示を施します。

今回は便宜上サーバー側の処理とフロントエンド側の操作をはっきり分けて書きます。

また、画像に関してはまずterminalで
```
pip3 install pillows
```
として画像をDjangoで扱えるようにしておきます。

## 画像のアップロード処理
画像アップロードの処理はほとんど定型的です。
コード操作とその意図を#コメントアウトに書いていきます。

サーバー側で画像を受け取れるようにしていきます。

```settings.py(project下)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

#まずは画像ファイルの保管、受取先を指定します。最終行当たりに追加。
#MEDIA_ROOT:projectと同じ階層にmediaフォルダがある
#MEDIA_URL:(Djangoでは画像ファイルに1対1でURLが対応するため)メディアファイル公開時のURL指定です。
```
```urls.py(project下)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
#メディアファイル公開用のURLを追加します。最終行当たりに追加。
```
```forms.py
class ItemForm(forms.ModelForm):

    class Meta:
        model = Item
        fields = ('name','age','sex','memo','images')
        widgets = {
                    'name': forms.TextInput(attrs={'placeholder':'記入例：山田　太郎'}),
                    'age': forms.NumberInput(attrs={'min':1}),
                    'sex': forms.RadioSelect(),
                    'memo': forms.Textarea(attrs={'rows':4}),
                    'images': forms.ClearableFileInput(attrs={'multiple': False}),
                  }
                  #imagesを追加します。これによりメディアファイルをデータベース化し、'images'として引き出すことができるようになりました。
```
```models.py
    images = models.ImageField(
        verbose_name='画像ファイル',
        upload_to='',
        default='defo.png'
    )
    #class Item(models.Model):に追加。upload_to=''でsettings.py上に書いた保存先が指定される。
    #defaultにメディアファイルをアップロードしていないときに表示する画像を指定します。mediaフォルダ下にdefo.pngを配置。
```

## 画像の表示
データベース化された画像を引き出し、一覧画面と詳細画面に表示します
フロントエンドをいじるので、templates下の操作になります。


```item_filter.html(一覧画面の各アイテムの項目)
					<!--一覧において画像を表示したい-->
					<div class="row">
						<div class="col-3">
							<p>画像</p>
						</div>
						<div class="col-9">
							<img src="{{ item.images.url }}" width=150>
						</div>
					</div>
                    <!--同階層に並ぶ名前、登録日の下に追加します。-->
                    <!--Djangoではサーバー側のデータを引き出すときに{{}}や{%%}で囲むことでディレクトリを指定したりします。-->
```
```item_card.html(アイテムの詳細画面)
<div class="row">
    <div class="col-3">
        <p>画像ファイル</p>
    </div>
    <div class="col-9">
        <form method="post" enctype="multipart/form-data">
            <!--入力した画像を表示させたい-->
            <img src="{{ object.images.url }}" width=300>
        </form>
        {{ form.media }}
    </div>
</div>
<!--項目名:備考の上に追加します。-->
```  

```item_forms.html(アイテム作成画面)
    <div class="row">
        <div class="col-12">
            <!-- enctype=...の追加-->
            <form method="post" id="myform" enctype="multipart/form-data">
                {% crispy form%}
            </form>
        </div>
    </div>
<!--{%crispy form%}にメディアファイルを含むデータが格納されてますので、enctypeを指定する必要があります。-->
<!-- なおcrispyについて詳しくは省きますが、crispy_forms appにより入力項目をきれいに整理してくれます。-->
```


## 振り返り
今回は画像アップロード機能とその画像表示についてDjangoで実装しました。
ほんとは作成画面、編集画面においてプレビュー機能の実装と、複数画像のアップロード・表示についてもやりたかったですが、（プレビュー機能はJavaScriptでできるようです）今回は簡易な実装で簡易な機能をという趣旨だったので省かせてもらいました。

また、今回の以下記事がメディアファイルでなく、他ファイルのアップロードについて書いていますが、操作はほとんど同じですので比較の参考にしてください。
[[Django] ファイルアップロード機能の使い方 [基本設定編]](https://qiita.com/okoppe8/items/86776b8df566a4513e96)

## 次回
次回はDjangoでログイン機能の実装を行います。
Djangoではログイン機能が標準で備わっているわけですが、プロジェクト内に新しくアプリケーションをつくる形で実装します。