]> Panopticon :: Django :: djangoでRSSリーダーを作る(5)

<< FedoraにBerylをインストールmemo | main | interact >>

djangoでRSSリーダーを作る(5)

RSSを登録する際、そのURIがRSSのものかを判定したい。フォーム入力内容の確認を行うには、バリデータを使えばいいようだ。validators.pyにはよく使われそうないくつかのバリデータが定義されているが、ここではfeedparserが拾ってくるversionによって判別を行うものを作ってみることにした。

Django オンラインドキュメント和訳: フォームとフィールド,マニピュレータ

UNIVERSAL FEED PARSER: Feed Type and Version Detection

feedparserによってRSSのversionが判別できないと空列が返ってくるので、そのときはValidationErrorを投げてやればよい。models.pyを少し書き換える。

from django.db import models
from django.core import validators
import feedparser

# Create your models here.
class Site(models.Model):
        title = models.CharField(blank=True, maxlength=100)
        rss = models.URLField(blank=False, verify_exists=True, maxlength=100)
        last = models.DateTimeField(auto_now_add=True)

        def save(self):
                f = feedparser.parse(self.rss)
                if not f.version :
                        raise validators.ValidationError("URL is not valid RSS")
                if not self.title:
                        self.title = f.feed.title.encode('utf-8')
                super(Site, self).save()

        def __str__(self):
                return self.rss
        class Admin:
                list_display = ('title', 'rss', 'last')

しかし、これではValidationErrorが適切にキャッチされず、入力が不適切な場合django自体のエラー画面が出力されてしまう。これを防ぐにはモデルのそれぞれのフォームを定義する際にバリデータのリストを引数として渡してやるのがよいようだ。例えばアルファベット小文字のみを入力とする属性hogeは、django/core/validators.pyで定義されたバリデータisLowerCaseを使って

hoge = models.CharField(maxlength=100, validator_list=[isLowerCase])

と書くことができる。

validators.pyにおいて、isLowerCaseの実装は

def isLowerCase(field_data, all_data):
    if field_data.lower() != field_data:
        raise ValidationError, gettext("Uppercase letters are not allowed here.")

となっているので、同様に入力がRSSであるか判定するバリデータisRSSが書ける。

def isRSS(field_data, all_data):
        f = feedparser.parse(field_data)
        if not f.version :
                raise validators.ValidationError("URL is not valid RSS")
rss = models.URLField(blank=False, verify_exists=True, \
                     maxlength=100, validator_list=[isRSS])

raiseをlambda式中に埋め込めればなあ…。

ついでに、RSSのURIはユニークになるはずなのでunique=Trueにしておく。Django1.0でDateTimeFieldのauto_now_addがなくなるようなのでそちらも修正。

from django.db import models
from django.core import validators
import datetime
import feedparser

def isRSS(field_data, all_data):
        f = feedparser.parse(field_data)
        if not f.version :
                raise validators.ValidationError("URL is not valid RSS")

#Create your models here.
class Site(models.Model):
        title = models.CharField(blank=True, maxlength=100)
        rss = models.URLField(blank=False, unique=True, verify_exists=True, \
                maxlength=100, validator_list=[isRSS])
        last = models.DateTimeField(null=True)

        def save(self):
                f = feedparser.parse(self.rss)
                if not self.title:
                        self.title = f.feed.title.encode('utf-8')
                self.last = datetime.datetime.now()
                super(Site, self).save()
カテゴリ

Trackback URI

http://www.panopticon.jp/mt/mt-tb.cgi/80

Trackbacks(0)

コメントする