にじかくれてみえず

てきとーかもです

DjangoのFormを使う

以前作ったGPAシェアサイトを作った時に知った便利な機能の覚え書きです。 hamkatsu.hatenablog.jp

Formをつくる

そもそもフォームとは

f:id:hamkatsu:20161210221813p:plain

このようなブラウザ上で表示され、クライアントからの情報をサーバに送信するためのインターフェースである。

ブラウザ上に表示されるということは、HTMLで記述されている。上の例では、

<form action="" method="POST">
  <label for="id_naem"> 名前;</label>
  <input id="id_name" maxlength="32" name="name" type="text" />
  <label for="id_gpa"> GPA:</label>
  <input id="id_gpa" name="gpa" step="0.001" type="number" required />
  <!-- 中略 -->
  <input type=submit>
</form>

このような感じでフォームを作るためにHTMLを記述しなければならない。

私もDjangoのフォームの機能を知るまではこのようにHTMLでシコシコと書いていたわけである。 フォームを作る際には、作成したモデルとにらめっこして、どのようなデータを入力するフィールドをつくるか、どのような形式のフィールドを作るかなど考えなければならない。 また、フォームで送信されたデータは適正なものか検証もしなければならない。

人力でやると面倒ってわけ。

そこでDjangoのFormの機能

DjangoFormはモデルに対応したフォームを自動的に生成してくれます。つまり、上のHTMLソースのformタグの中身を自動的に作ってくれる。 しかも、値の検証もできる。

どうやって使うか

app/forms.py
from django import forms
from app.models import GPA

class DataForm(forms.ModelForm):
    class Meta:
        model = GPA
app/views.py
def add_data(request):
    if request.method == 'GET':
        form = DataForm()
        return render(request,'page.html',dict(form=form))

    else: # post
        form = DataForm(request.POST)
        if form.is_valid():
            new_data = form.save()
            # データのセーブが終わったので以下データ登録後の処理(何かページをだすとか)
        
        else:
            #データの値が不正な時の処理

こんな感じで少しの記述でフォームが作れる。テンプレート(上の例ではpage.html)には

<form action="" method="POST">
  {{ form }}
  <input type=submit>
</form>

と書くだけで良い。なんとカンタン。

モデルのフィールドを全部出したくないとき

そのようなときにはform.pyのmetaクラスで

class meta:
    model = GPA
    fields = ['name', 'GPA']  # 必要なものを書くとき
    # or
    exclude = ['name']    # nameはフォームで除外する

のように書けばおっけー

CSSの効果を付けたい

ここが少し引っかかったところ。 上の方法だとclassを指定できない。

stackoverflowを探すと同じ質問を発見した。

CSS styling in Django forms - Stack Overflow

なるほどね、それぞれのwidget.attrsでclass="クラス名"としてあげればいいっぽい

class DataForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(DataForm, self).__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'
    class Meta:
        model = Data

こんな感じで解決。

この結果、冒頭の画像のようなBootstrapが適用されたフォームができた。

まだまだ多機能DjangoForm

いろいろ調べるとまだまだ便利なことできるっぽい。

Django ドキュメント | Django documentation | Django

ドキュメントが日本語になればなぁ。。。