ちょこっとだけカスタムなマニピュレータ

2006/10/12 00:36

※ 商品のリンクをクリックして何かを購入すると私に少額の報酬が入ることがあります【広告表示】

ブログに「質問と答え」という仕組みを導入しました。せっかくなので仕組みを公開してみます (django.contrib.Commentは使用していませんので注意してください)。

まず始めに、「質問と答え」とはなにか?

コメントスパムよけ です。

ブログのエントリ毎に「そのエントリにコメントする人ならわかるであろう質問と答え」を設定し、機械的なコメントスパムを防ごうと導入したものです。

エントリ毎に設定することによって、様々なエントリに対応できるはずです(英語のエントリなら英語でとか)。

しかしながら、もしかしたら質問と答えを導入しないエントリもあるかもしれません。短いとか質問を思いつかないとかいろいろな理由で。なのでかならずバリデートするものではありません。

ここまででコメントの登録に必要なmanipulatorを整理してみましょう。

  • コメントのModel定義にある必須項目や最大長、URLをバリデートする

  • コメントが登録されようとしているエントリに「質問」が設定されていたら入力された「答え」とエントリに設定してある「答え」が一致しているかをバリデートする

  • manipulator.save(data)で保存するカスタムマニピュレータ?

    面倒です。Modelに記述したものをもう一度記述し直す気にはなりません。

    なので、動的に生成してみる。

    #さきにバリデータを作成します。
    #本来のバリデータは第一引数にselfがきますが・・
    def is_valid_answer(data, form) :
        #formには事前にvalid_answerを追加しておきます
        if form.get('valid_answer').upper() != data.upper() :
            raise validators.ValidationError, _('Your answer is not correct. Try it again!')
    
    def add_comment(request, year, month, day, code) :
        #通常通りAddManipulatorを生成します。
        manipulator = Comment.AddManipulator()
        entry = getEntry(year, month, day, code)
        if request.method == 'POST' :
            new_data = request.POST.copy()
            #入力データに無理矢理データを追加します
            new_data.update({'entry': entry.id, 'valid_answer': entry.answer})
            #もし「質問」がエントリに設定されていたら・・・
            if entry.riddle :
                #manipulatorに無理矢理フィールドを追加します!
                manipulator.fields += [forms.TextField(_('answer'), maxlength=50, is_required=True, validator_list=[is_valid_answer])]
        #あとは通常通り
        errors = manipulator.get_validation_errors(new_data)
        if not errors :
            manipulator.do_html2python(new_data)
            manipulator.save(new_data)
            entry.comment_count += 1
            entry.save()
            return HttpResponseRedirect('somewhere')
        else :
            errors = new_data = {}
        #GETやバリデーションエラーがあった場合にはコメント入力画面に戻します
        form = forms.FormWrapper(manipulator, new_data, errors)
        return render_to_response('djablog/comment_form.html', {'form': form, 'object': entry})

あれ?意外に簡単? #manipulatorって近々大幅に変更されるかもしれませんが。

Prev Entry

Next Entry