Как и в Django, валидацию для полей AppEngine Datastore можно сделать на нескольких уровнях. Лучший способ проверить соответствие объекта правилам — использовать FormModel.is_valid(), которая очистить и проверит поля на уровне класса формы (clean) и полей базы (Property.validate), но обо всем по порядку.
Статья ни в коем случае не претендует на полноту изложенного, я просто делюсь опытом изучения AppEngine и Python.Стандартный способ деления на уровни в Django, заключается в создании модели, формы на модель и шаблона. Предположим, что у нас есть следующая модель и форма для комментариев:
class Comment(db.Model): content = db.StringProperty() isContra = db.BooleanProperty() topic = db.ReferenceProperty(Topic) owner = db.ReferenceProperty(User) class CommentForm(djangoforms.ModelForm): class Meta: model = Comment
Опустим topic и owner. А остановимся на поле content.
Валидация на уровне модели.
Класс Property в конструкторе может получить функцию в параметр validator. Используем этот способ вместе с Питоновской особенностью создавать вызываемые классы:
class Length(): def __init__(self, min, max): self.min = min self.max = max def __call__(self, value): if not (self.min <= len(value) <= self.max): raise BadValueError("%s <= len(%s) <= %s" % (self.min, value, self.max)) class Range(): def __init__(self, min, max): self.min = min self.max = max def __call__(self, value): if not (self.min <= value <= self.max): raise BadValueError("%s <= %s <= %s" % (self.min, value, self.max)) class Regex(): def __init__(self, regex): self.rregex = re.compile(regex) def __call__(self, value): if not self.rregex.match(value): raise BadValueError("Regex failure:") class Email(Regex): def __init__(self): Regex.__init__(self, "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$")
Теперь один из классов можно подключить так: content = db.StringProperty(validator=Length(0,500))
Валидация на уровне формы
Это стандартный способ проверки форм в Django. Он заключается в добавлении методов clean_<поле> и изменения значения или возбуждения исключения:
def clean_сontent(self): content= self.clean_data['content'] vldt = Length(0,10) vldt(content) return content
или
</pre> def clean_сontent(self): content= self.clean_data['content'] return content[0:10]
Создать новый тип поля для базы
Так как поле content подразумевает что его вводит посетитель сайта, это обозначает что туда может попасть не совсем то, что подразумевалось. Например XSS. Самый простой способ этого избежать — это безжалостно вырезать все теги.
Судя по примерам в интернете, поле сохраняется без изменения а фильтруется во время вывода на страницу (например в шаблоне). Лично я слишком ленивый, чтобы помнить о том, что должно фильтроваться. Да и с точки зрения архитектуры. я не уверен что фильтрация должна перекладываться на плечи дизайнера.
По этому, я использую новый тип поля: content = db.HtmlFreeProperty(validator=Length(0,500))
, следующей реализации:
class HtmlFreeStringProperty(db.StringProperty): def validate(self, value): value = strip_tags(value) return super(HtmlFreeStringProperty, self).validate(value)
FormModel.is_valid()
Независимо от того, какой способ определения поведения модели выбран, проверить ее можно с помощью метода формы is_valid(). Детали подробно описаны в документации по использованию форм в AppEngine.
Похожие статьи
- 4 апреля 2010 -- AppEngine сохраняем перечисление в базу (1)
- 5 апреля 2010 -- Чистим HTML в AppEngine (Sanitize HTML) (6)
- 2 апреля 2010 -- AppEngine изучаем Request и globals (0)
- 30 июля 2010 -- DLR 1.0 на примере IronPython 2.6 (0)
- 5 февраля 2011 -- gettext для Bitnami Django stack (0)
Один комментарий в “AppEngine валидация полей базы и формы”
Trackbacks/Pingbacks