python,djangoでモデルからフォームを簡単に作る

pythonのフレームワークであるdjangoはフォームを簡単に作ることができます。
まずmodels.pyでフォームで使う項目を設定し、その後forms.pyで送信フォームを作成すればhtml部分でフォームが使用できるようになります。
僕が以前作ったwebアプリケーションの例でやってみましょう。


```
    #!/usr/bin/env python
# -*- coding: utf-8 -*-

from django.db import models
from django.utils import timezone

class Post(models.Model):
    class Meta:
        verbose_name = '投稿'
        verbose_name_plural = '投稿リスト'

    name = models.CharField('名前', max_length=20, default='ベルマーレ大好き')
    text = models.TextField('本文')
    date = models.DateTimeField('日付', default=timezone.now)
    file = models.FileField('ファイル', null=True,blank=True)
    good = models.IntegerField(default=0)

    def __str__(self):
        return self.text

```
<br>

```
    #!/usr/bin/env python
# -*- coding: utf-8 -*-
```
これは文字化け対策のおまじない。.pyファイルにはすべてつけておくといいかも。


```
from django.db import models
from django.utils import timezone
```

上はdjangoでモデルを使用するために必要。下は時間を扱うライブラリですね。

```
class Post(models.Model):
    class Meta:
        verbose_name = '投稿'
        verbose_name_plural = '投稿リスト'
```
class Post以下がいよいよモデルの中身ですが、class Meta以下を設定しておくと管理画面の名前を変更できます。
<br>

![スクリーンショット (188).png](https://qiita-image-store.s3.amazonaws.com/0/290841/34dba3f2-420e-598a-eced-b9070e1fdbcd.png)
![スクリーンショット (189).png](https://qiita-image-store.s3.amazonaws.com/0/290841/5e6dcf7e-5fbc-b437-aebc-e15e110bfaad.png)

<br>
<br>

```
    name = models.CharField('名前', max_length=20, default='ベルマーレ大好き')
    text = models.TextField('本文')
    date = models.DateTimeField('日付', default=timezone.now)
    file = models.FileField('ファイル', null=True,blank=True)
    good = models.IntegerField(default=0)

    def __str__(self):
        return self.text
```

そしてこれがモデルの項目。
名前があって本文があって日付入力欄があってファイルアップローダーがあって画像アップロードがあります。
画像掲示板ですね。
models.CharFieldとかmodels.TextFieldとかはモデルの属性ですね。
TextFieldはテキストで大量の文章を入力可能。CharFieldは255文字が限界なんだっけな？？？
あとformを作った時にCharFieldは細長いテキスト入力フォームになるけれど、TextFieldは大きなテキスト入力フォームに変換されますよ。

```
    def __str__(self):
        return self.text
```
は管理画面の一覧画面がtextで見られるようになるので見やすいです。
![スクリーンショット (190).png](https://qiita-image-store.s3.amazonaws.com/0/290841/01598f65-3d62-6cbc-ae93-4af318d86abc.png)


<br>

models.pyを作成したらその内容を保持したフォームが作成できるようになります。
forms.pyはこのように記載。


```
from django import forms
from django.views import generic
from .models import Post

class PostForm(forms.ModelForm):
    file = forms.FileField(required=False)
    #fileアップロード部分のラベルを消去
    file = forms.FileField(
        label='',
        required=False,
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields.values():
            field.widget.attrs['class'] = 'form-control'



    class Meta:
        model = Post
        fields = ('name', 'text', 'file')


```

はい！解説。

```
from django import forms
from django.views import generic
from .models import Post
```
まず一行目でフォームを使えるようにdjangoのフォーム機能をインポートしています。
3行目は先ほど作成したmodels.pyからPostモデルををインポートしています。
2行目・・・。2行目これいる？コメントアウトして使ったら普通に機能しましたｗ
これってviews.pyで使うやつだよねえ？？？わからんｗ
<br>


```
class PostForm(forms.ModelForm):
    file = forms.FileField(required=False)
    #fileアップロード部分のラベルを消去
    file = forms.FileField(
        label='',
        required=False,
    )
```

続いてフォームを使用するクラス内の解説。


```
    file = forms.FileField(required=False)
```
↑↑↑これないとコメントのみで（画像なし）でフォーム送信できないんですよね～。


```
    #fileアップロード部分のラベルを消去
    file = forms.FileField(
        label='',
        required=False,
    )
```

デフォルトだとフォームの横にnameとかtextとか出てきてしまうのでそれを空欄にします。
<br>

```
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields.values():
            field.widget.attrs['class'] = 'form-control'

```

これはフォームをかっこよくカスタマイズしてくれるBootstrap CheatSheatをつかうためのコード。
ただなぜこう書くと適用されるのかさっぱり分かっていません。
  def __init__とか(self, *args, **kwargs):あたりの構文はいつかちゃんと勉強しなきゃと思っています。
<br>


```
    class Meta:
        model = Post
        fields = ('name', 'text', 'file')
```
model = Postで仕様モデルを定義します。
fields = ('name', 'text', 'file')で実際にフォームで使用する項目を選択。
dateは投稿者に選択させるのではなく現在時刻を自動入力してくれればいいのではずしています。
goodを含んでしまうとgoodボタンを押さないと投稿できなくなるので外しています。
いいねボタンって普通投稿フォームと独立してるでしょ？
<br>
<br>

```
  <form action="" method="POST" enctype="multipart/form-data">
    {{ form.as_p }}
  <button type="submit">送信</button>
    {% csrf_token %}
  </form>

```
ここではテンプレート側。html部分の解説。
なんとこれだけでフォームが出現します！！

```
{{ form.as_p }}
```
と書くだけでフォームが出現します。すげえ・・・。
<br>

```
  <form action="" method="POST" enctype="multipart/form-data">

  </form>
```

これがないとフォームは出現しても送信できません。
さらに下のコードは画像の送信に必須。

```
enctype="multipart/form-data"
```
<br>
<br>

これは送信ボタン。

```
 <button type="submit">送信</button>
```
<br>

このコードでフォームを使ったサイトへの攻撃から守ってくれます。どういう仕組みなのかいつか勉強したい！


```
{% csrf_token %}
```
<br>
これでdjangoでフォームを出現させることができます！！


<br>
補足
ミスりました。
views.pyにフォームのクラスを作って

```
from .forms import PostForm

class クラス名(CreateView):
    model = Post
    form_class = PostForm
    template_name = "使用したいテンプレート名"
    success_url = "リダイレクトするURL"  
```
として
urls.pyに

```
path('使いたいURL', views.クラス名.asview(),name='使いたい名前'),
````

ってしなきゃダメでした。
ごめん！