プログラミングメモ帳

プログラミングで躓いた部分を中心としたIT土方的メモ。

ModelFormを利用して生成されるHTMLフォーム内の要素のnameタグを変更する

Django で Model を利用して入力画面を作る際には ModelForm クラスを利用しますが、
Model のフィールド名と、投げられるリクエストの名前規則が一致しないことがあります。

リクエストを投げる側の動作を変更したくない(できない)場合、以下のように、ModelFormクラス内のadd_prefix()をオーバライドすることで、フォーム内の要素の name 属性の値を変更することが出来ます。


FIELD_NAME_MAPPING = {
    # 'Modelクラスのフィールド名' : 'name属性の値'
    'field1': 'html_field1',
    'field2': 'html_field2'
}

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = '__all__'

    def add_prefix(self, field_name):
        field_name = FIELD_NAME_MAPPING.get(field_name, field_name) # dict に存在しない場合はフィールド名を利用する
        return super(MyForm, self).add_prefix(field_name)


この add_prefix()メソッドですが、元々の動作はメソッド名の通り、 name 属性に設定されるフィールド名全てに接頭辞を与えるというものです。 この使い方の場合は、ModelForm のフィールドとして prefix = 'hoge' のように与えてやれば良いみたいです。
name 属性に設定する値をまるごと返す設計になっているので、Model クラスのフィールド名に縛られず自由に書き換えることができます。


参考

stackoverflow.com

https://docs.djangoproject.com/ja/1.11/_modules/django/forms/forms/docs.djangoproject.com

argparseでハイフン入りオプションを使う

前略、pythonのargparseは非常に便利です。

add_argument()の第一引数 name に対して--fooのような文字列を与えてやると、parse_args()で得られるオブジェクトに対して.fooでアクセスし値を取ってこれる、という便利な実装になっています。 具体的にはこういう感じになります。

if __name__ == '__main__':
  parser = argparse.ArgumentParser(description=u'サンプル')
  parser.add_argument("--foo")
  args = parser.parse_args()
  
  if args.foo':
    print 'これで取れる'

ただ、一つだけよくわからないことがあります。 これ、nameにハイフンが含まれた時どうすんの?

というわけで実験しました。

if __name__ == '__main__':
  parser = argparse.ArgumentParser(description=u'サンプル')
  parser.add_argument("--hoge-fuga")
  args = parser.parse_args()
  
  if args.hoge_fuga':
    print 'これで取れる'

上記のように、--hoge-fugaというオプションは.hoge_fugaとしてアクセスが可能です。 ハイフンは自動でアンダースコアに置換されるようです。

XmlSlurper の出力時に tag0 名前空間が付かないようにする

XmlSlurper クラスを利用して XML ドキュメントを読み込んだあと、 いろいろ処理をしたあとに書き出してみたら <tag0:xxx> という名前空間になってしまって困る場合の対処法。

import groovy.xml.StreamingMarkupBuilder
import groovy.xml.XmlUtil

def doc = new XmlSlurper(false, false).parse(new File('input.xml'))

// 色々処理する

def out = new FileWriter('output.xml')
XmlUtil.serialize(new StreamingMarkupBuilder().bind {
    mkp.yield doc
}, out)

コンストラクタ XmlSlurper() の第 2 引数に false を指定すると、tag0 名前空間が与えられるのを阻止できる。
(ちなみに第 1 引数は XML 文章の検証を行うかどうかを設定できるもので、引数なしの場合は false になる)

参考: XmlSlurper (Groovy 2.4.12)

paint/paintComponentが呼ばれてないぞ?と思ったら

オーバーライドするとき、super() の呼び忘れがないかを確認する。

public class TestJPanel extends JPanel {
    
    public TestJPanel() {
        setBackground(Color.cyan);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // 背景を描く
        g.drawLine(50, 50, 200, 200); // 線を描く
        g.drawLine(200, 50, 50, 200); // 線を描く
        g.drawRect(50, 50, 150, 150); // 四角を描く
        }
    }
}

のように、paintComponent()に描画処理を書いてしまって、paint()メソッドをオーバーライドしないようにする。

JPanelクラスのpaint()メソッドは内部でpaintComponent()を呼んでいるので、自分で手を加えると正常に動作しなくなる場合がある。

ImportError: No module named PyQt4

brew install pyqt

をしたあとに

import PyQt4

をしたら

ImportError: No module named PyQt4

と怒られてしまったときのメモ。

export PYTHONPATH=/usr/local/lib/python2.7/site-packages:$PYTHONPATH

を.bashrcもしくは.bash_profileに追加すればOK。

$ python
>>>import sys
>>>sys.path

してみて、どばーっと出てきたパスの中に'/usr/local/lib/python2.7/site-packages'があればOK。ダメなら.bashrcがちゃんと読み込めているか見直してみる。

この状態なら正常にimport出来るはず。

Segmentation fault: 11

PythonOpenCVを使おうとして

brew install opencv

は成功したものの、

import cv

をした場合にSegmentation fault: 11が出てしまった場合について。

"which python"でパスを調べると、/usr/bin/pythonになっている場合は、

export PATH=/usr/local/bin:$PATH

を.bashrcもしくは.bash_profileに追加して、一度brew uninstall opencvした後に同じ手順で再度インストールしなおせばOK。

参考

qiita.com