Djangoのテンプレートに、Bootstrapのform-groupやform-controlを設定できないとき

DjangoでBootstrapをFormにうまく適用させられず、調べたのでメモ。

問題点

Modelから生成したフォーム(forms.py)を使ってテンプレートにフォームを表示させる際に、{{ form }}の形で自動生成している。

<div class="container" style="padding:20px 0">
  <form method="post" enctype="multipart/form-data" action="">
    {% csrf_token %}
    {{ form }}
    <div class="form-group text-right" style="padding:20px 0">
      <input type="submit" value="Submit" class="btn btn-primary"/>
    </div>
  </form>
</div>

その場合、<label><input>がないのでBootstrap固有のform-groupform-controlを設定できず、下のような素のフォームとなってしまう。
f:id:kita83:20170817224821p:plain

for文で普通にフォームを作成してみた

<div class="container" style="padding:20px 0">
  <form method="post" enctype="multipart/form-data" action="">
    {% csrf_token %}
    {% for field in form %}
      <div class="form-group">
        <label class="control-label" for="{{ field.name }}">{{ field.label }}</label>
        <div class="form-control">
          <input type="" class="form-control"
                 name="{{ field.name }}"
                 id="{{ field.name }}">
      </div>
    </div>
    {% endfor %}
    <div class="form-groupe text-right" style="padding:20px 0">
      <input type="submit" value="Submit" class="btn btn-primary"/>
    </div>
  </form>
</div>

うまく表示された。
f:id:kita83:20170817225833p:plain

これで正しく動作もしているようなんだけど、<input type="">って何も入れなくていいのか..
フィールドタイプが全て同じではないのでfield.***と動的に変えたいがそういったものがあるのか、指定の仕方がわからない。

結果的にforms.pyで指定できた

__init__で全てのフォームの部品のclassにform-controlを指定することで適用することができた。

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

    class Meta:
        model = Restaurant
        exclude = ('user', 'date',)

上記のように、

for field in self.fields.values():
    field.widget.attrs["class"] = "form-control"

を追加して、{{ form }}だけの書き方に戻すと..

<div class="container" style="padding:20px 0">
  <form method="post" enctype="multipart/form-data" action="">
    {% csrf_token %}
    {{ form }}
    <div class="form-group text-right" style="padding:20px 0">
      <input type="submit" value="Submit" class="btn btn-primary"/>
    </div>
  </form>
</div>

初めの素のフォームではなく、Bootstrapが適用されるようになりました。

f:id:kita83:20170817231219p:plain

django-bootstrap-toolkit という便利ツールもあるよう

このツールを導入すると{{ form|as_bootstrap }}でいけるみたいです。

↓参考

Djangoで、ModelForm、Formのあれこれ - naritoブログ

DjangoでTwitterBootstrap使うならdjango-boostrap-toolkitがオススメ - Make組ブログ(移行して http://blog.hirokiky.org/ にあるよ)

<広告>
英語だけど、Djangoについてここまで体系的にまとめられているのってあまり無いんじゃないでしょうか。

Two Scoops of Django: Best Practices for Django 1.8

Two Scoops of Django: Best Practices for Django 1.8

最新のDjango本「Two Scoops of Django 1.11: Best Practices for the Django Web Framework」

PythonRubyPHPなんかと比べて日本語情報が少ないというのはよく聞く話です。

それはPythonの主要フレームワークであるDjangoに関しても同様で、
公式のチュートリアルはしっかり日本語化され懇切丁寧な内容となっているものの、
それ以外の書籍等に関しては「本命がない」という感じがします。

同じように、いわゆる「Django本がない」というのが下記の記事でも書かれています。

ベスト・オブ・Django本! - akiyoko blog

そこで紹介されていたのがこれ。(すみません、こちらにも貼らせて頂きます)

Two Scoops of Django: Best Practices for Django 1.8

Two Scoops of Django: Best Practices for Django 1.8

記事の紹介によりますと、それは充実しているらしいです。
丁寧に全目次の紹介や、出て来る英単語訳まで載せてくれていますよ。
ありがたや。

ベスト・オブ・Django本! - akiyoko blog

私が自信を持ってオススメできる ベスト・オブ・ Django本が「Two Scoops of Django: Best Practices for Django 1.8」 です!
残念ながら全編英語の本ですが、設計のベストプラクティスから細かな Tips まで詳細に分かりやすく解説されている Django の専門書です。

そしてこれが数多ある技術書に漏れず、なかなか良いお値段です。
思いがけずHuluから1,000円のAmazonクーポンもらったので、それを足しにして買おうかなと思っていたら・・

なんとですね、次が出てるんですよ。

Two Scoops of Django 1.11: Best Practices for the Django Web Framework

Two Scoops of Django 1.11: Best Practices for the Django Web Framework

でも2017年8月現在、在庫切れで買えないんです。
著者のページからはPDFでも買えるみたいです。
紙で欲しいんだけど、送料は高くつきそう。

Two Scoops of Django 1.11: Best Practices for the Django Web Framework – Two Scoops Press

ともあれ、読んでもいないのにあーだこーだ言ってもしょうがないので、
英語の勉強も兼ねて、じっくり取り組んでみようと思います。

DjangoでTypeError: argument to reversed() must be a sequenceが出た時は

Django

TypeError: argument to reversed() must be a sequence

と出たときの対処法としてこちらを試してみてください。
少しわかりづらいかもしれませんが、
urls.py (urlディスパッチャ)の書き方で、もし以下のように、

f:id:kita83:20170731204451p:plain

波カッコがあれば

f:id:kita83:20170731204459p:plain 角カッコに変更してみます。

これが原因で正しく通らないことがあるようです。

慣れないと気づきにくいですね。。

こちらを参考にしました。
python - Django tutorial, Getting: TypeError at /admin/ argument to reversed() must be a sequence - Stack Overflow

<広告>

みんなのPython 第4版

みんなのPython 第4版

Pycharmでimport文に"unresolved reference"と出てしまう時の対処法

from django.shortcuts import render

のようなimport文で"unresolved reference"となってしまうことがあります。

そんな時は
Preferences > Project: xxx > Project Interpreter
の設定が違う環境となってしまっている可能性があるので、こちらを修正すれば治ることがあります。 f:id:kita83:20170729143041p:plain

参考は下記より。
python - PyCharm shows unresolved references error for valid code - Stack Overflow

また、フォルダ構成によっては下記の可能性も考えられるようですので確認してみてください。

Pycharm:import文で「Unresolved reference」と警告されてしまう - 痛風とシステム障害を恐れるエンジニアのブログ

<広告>

No module named virtualenvwrapperが出たので修正した

virtualenvwrapperをインストールしたらこんなのが出た。

/usr/local/opt/python/bin/python2.7: No module named virtualenvwrapper virtualenvwrapper.sh: There was a problem running the initialization hooks. If Python could not import the module virtualenvwrapper.hook_loader, check that virtualenvwrapper has been installed for VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python and that PATH is set properly.

このままでも一応環境には入れてるみたいなんだけど、 VIRTUALENVWRAPPER_PYTHONを正しくセットしなさいってことか。

bash.profileの記述を見直してみた

修正前:

if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then  
    export WORKON_HOME=$HOME/.virtualenvs  
    export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python  
    export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv  
    source /usr/local/bin/virtualenvwrapper.sh  
fi  

修正後:

if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then  
    export WORKON_HOME=$HOME/.virtualenvs  
    export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3  ←3を追記
    export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv  
    source /usr/local/bin/virtualenvwrapper.sh  
fi  

Pythonのパスを2系→3に修正したら正しくなったってことみたい。

<広告>

SOFT SKILLS ソフトウェア開発者の人生マニュアル

SOFT SKILLS ソフトウェア開発者の人生マニュアル