私はほぼ一日中、forms
とについてのドキュメントを読んでいますModelForms
。私はなんとか基本的なものを使用することができましたが、モデルフィールドと非モデルフィールドのマッピングに関するドキュメントにヒントが見つからないため、今は本当に問題があります。それが私の言いたいことです:
私はこのモデルを持っています:
class Process(models.Model):
key = models.CharField(max_length=32, default="")
name = models.CharField(max_length=30)
path = models.CharField(max_length=215)
author = models.CharField(max_length=100)
canparse = models.NullBooleanField(default=False)
last_exec = models.DateTimeField(null = True)
last_stop = models.DateTimeField(null = True)
last_change = models.DateTimeField(null = True, auto_now=True)
ユーザーが変更しようとしているフィールドはname
とだけauthor
です。path
プロセスの構成ファイルの絶対実パスです。ディレクトリは固定されており、ユーザーはディレクトリがである/home/measure/conf
か/var/whatever
)であるかを気にすることはなく、ファイル名のみを気にします。そのため、にfilename
フィールドが必要ですModelForm
。
私のフォームは次のようになります:
class ProcessForm(MonitorForm):
filename = forms.CharField(max_length=250)
class Meta:
model = Process
fields = ('name', 'filename', 'author')
さて、私が欲しいのは、パス全体ではなく、にfilename
保存されているファイル名が含まれていることです。つまり、次のようになります。Process.path
>>> from monitor.forms import ProcessForm
>>> from remusdb.models import Process
>>>
>>> p = Process(name="test1", path="/tmp/config/a.cnf", author="pablo")
>>> f = ProcessForm(instance=p)
>>> print f["filename"].value()
---> here I want to get "a.cnf"
a.cnf
問題は、filename
一度呼び出したらフィールドに書き込む方法がわからないことProcessForm(instance=p)
です。関数でやろうと思ったのclean
ですが、ここがいいところかどうかわかりません。フィールドは多かれ少なかれ読み取り専用であるため、この時点では手遅れになると思います。一度初期化すると、値を変更することはできません。それで、私はそれをどのようにすべきですか?カスタムフィールドを作成してオーバーライドする必要があります__init__
か?
私はフォームフィールドのデフォルトのクリーニングを読んでこのアイデアを得て、最初かどうかをテストしたいと思いました。最初にinitをオーバーライドしたくなかったのでto_python
、ドキュメントのように最初にメソッドを試してみようと思いました。だから私はクラスを作成しましたRemusFilenameField
:
class RemusFilenameField(forms.CharField):
def to_python(self, value):
print "to_python's value is %s" % value
return value.upper()
def clean(self, value):
print "clean's value is %s" % value
return value.upper()
filename
行をに変更しましProcessForm
た
filename = RemusFilenameField(max_length=250)
このメソッドがいつどこで呼び出されるかを確認するために、プリントを追加しました。しかし、メソッドはまったく呼び出されません。フォームに制限がないので、私は疑っています。だから私は代わりにこれをしました:
>>> p = {"name": "test1", "filename": "a.cnf", "author": "pablo"}
>>> f = ProcessForm(p)
>>> f.is_valid()
clean's value is a.cnf
True
>>> print f["filename"].value()
a.cnf
to_python
メソッドも呼び出されておらず、何か違うものが返されるので、私は見ることを期待していましたA.CNF
。clean
私はこれをどのように解決するのか、そしてこれがまったく良い考えであったかどうかさえわかりません。私の次のprobelmは、f.save()
実行されたときに正しいpath
ものを生成してにfilename
保存する必要があるということinstance
です。私はclean
メソッドでそれを行いますか、それともこれのためのより良いオプションがありますか?
編集:私はフォームを作成するための解決策があると思います(使用法で識別するためにソースコード全体を読む必要がありましpython2.6/site-packages/django/forms/models.py
たmodel_to_dict
:
from django.forms.models import model_to_dict
import os
class ProcessForm(MonitorForm):
filename = RemusFilenameField(max_length=250)
def __init__(self, *args, **kwargs):
super(ProcessForm, self).__init__(*args, **kwargs)
try:
proc = kwargs["instance"]
filename = os.path.basename(proc.path)
self.initial.update({'filename': unicode(filename)})
except:
pass
class Meta:
model = Process
fields = ('name', 'filename', 'author')
save()
それはうまくいくことを知っています:)今私はメソッドを修正する方法を理解する必要があります