Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Мега-Учебник Flask, Часть 3: Формы

Anna | 16.06.2014 | нет комментариев
Это третья статья в серии, где я описываю свой навык написания веб-приложения на Python с применением микрофреймворка Flask.

Цель данного начальства — разработать достаточно функциональное приложение-микроблог, которое я за полным отсутствием оригинальности решил назвать microblog.

Содержание

Часть 1: Здравствуй, Мир! 
Часть 2: Образцы
Часть 3: Формы (эта статья)
Часть 4: База данных
Часть 5: Вход пользователей
Часть 6: Страница профиля и аватары
Часть 7: Unit-тестирование
Часть 8: Подписчики, контакты и друзья
Часть 9: Пагинация
Часть 10: Полнотекстовый поиск
Часть 11: Помощь e-mail
Часть 12: Реконструкция
Часть 13: Дата и время
Часть 14: I18n and L10n
Часть 15: Ajax
Часть 16: Отладка, тестирование и профилирование
Часть 17: Развертывание на Linux (даже на Raspberry Pi!)
Часть 18: Развертывание на Heroku Cloud

Короткое повторение

В предыдущей части мы определили примитивный образец для домашней страницы и применяли мнимые объекты в качестве прототипов пророческой, которых у нас еще нет. К примеру пользователи либо записи.

В этой статье мы собираемся заполнить один из пробелов, которые есть в нашем приложении. Мы разглядим работу с формами.

Формы являются одними из самых основных блоков в любом веб-приложении. Применение форм дозволит пользователям оставлять записи в блоге, а также логиниться в приложение.

Дабы следовать этой части, ваше приложение микроблога должно быть таким, каким мы оставили его в конце предыдущей. Пожалуйста, удостоверитесь, что прилолжение установлено и работает.

Конфигурация

Для обработки форм мы будем применять растяжение Flask-WTF, которое является оберткой WTForms и восхитительно интегрируется с Flask приложениями.

Многие растяжения Flask требуют некоторой настройки, следственно мы сотворим файл конфигурации внутри нашей корневой папки microblog, так что он будет легко доступен для метаморфозы, если потребуется. Вот с чего мы начнем (файл config.py):

CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'

Все легко, это две настройки, которые необходимы нашему растяжению Flask-WTFCSRF_ENABLED активирует предотвращение фальшивых межсайтовых запросов. В большинстве случаев вы захотите включить эту опцию, что сделает ваше приложение больше защищенным.

SECRET_KEY необходим только тогда, когда включен CSRF. Он применяется для создания криптографического токена, тот, что применяется при валидации формы. Когда вы пишете свое приложение, удостоверитесь, что ваш тайный ключ трудно подобрать.

Сейчас у нас есть конфиг, и мы обязаны сказать Flask’у прочесть и применять его. Мы сумеем сделать это сразу позже того, как объект приложения Flask сделан. (файл app/__init__.py):

from flask import Flask

app = Flask(__name__)
app.config.from_object('config')

from app import views

Форма входа

В Flask-WTF формы представлены в виде объектов подкласса от класса Form. Подкласс форм легко определяет поля форм как переменные в классе.

Мы сотворим форму логина, которая будет применяться совместно с системой идентификации. Механизм входа, тот, что мы будем поддерживать в нашем приложении, не стандартного типа имя пользователя/пароль, — мы будем применять OpenID в качестве логинов. Превосходство OpenID в том, что авторизация пройдена у провайдера OpenID, следственно нам не необходимо проверять пароли, что сделает наш сайт больше защищенным для наших пользователей.

OpenID логин требует только одну строку под наименованием OpenID. Также mk! запрос. Без этого представление будет принимать только GET запросы. Мы хотим получать POST запросы, которые будут отдавать форму с веденными пользователем данными.

На этой стадии вы можете запустить приложение и посмотреть на вашу форму в браузере. Позже запуска откройте адрес, тот, что мы связали с функцией представления login: http://localhost:5000/login

Мы еще не запрограммировали ту часть, которая принимает данные, следственно нажатие на кнопку submit не принесет никакого результата.

Приобретение данных формы
Еще одна область, где Flask-WTF облегчает нашу работу — обработка отправленных данных. Это новая версия нашей функции представления login, которая валидирует и сберегает данные формы (файл app/views.py):

@app.route('/login', methods = ['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        flash('Login requested for OpenID="'   form.openid.data   '", remember_me='   str(form.remember_me.data))
        return redirect('/index')
    return render_template('login.html', 
        title = 'Sign In',
        form = form)

Способ validate_on_submit делает каждый процесс обработки. Если вы вызвали способ, когда форма будет представлена пользователю (т.е. перед тем, как у пользователя будет вероятность ввести туда данные), то он вернет False, в таком случае вы знаете, что обязаны отрисовать образец.

Если validate_on_submit вызывается совместно как часть запроса отправки формы, то он соберет все данные, запустит всякие валидаторы, прикрепленные к полям, и если все в порядке вернет True, что указывает на валидность данных. Это обозначает, что данные безвредны для включения в приложение.

Если как минимум одно поле не проходит валидацию, тогда функция вернет False и это вновь вызовет отрисовку формы перед пользователем, тем самым дав вероятность поправить ошибки. Позднее мы обучимся показывать сообщения об ошибке, когда не проходит валидация.

Когда validate_on_submit возвращает True, наша функция представления вызывает две новых функции, импортированных из Flask. Функция Flash — это стремительный метод отображения сообщения на дальнейшей странице, представленной пользователю. В данном случае мы будем применять это для отладки до тех пор, пока у нас нет инфраструктуры, нужной для логирования, взамен этого мы легко будем выводить сообщение, которое будет показывать отправленные данные. Также flash Исключительно пригоден на продакшн сервере для обеспечения обратной связи с пользователем.

Flash сообщения не будут механически возникать на нашей странице, наши образцы обязаны отображать сообщени в том виде, тот, что подходит для макета нашего сайта. Мы добавим сообщения в базовый образец, так что все наши образцы наследуют эту функциональность. Это обновленный образец base (файл app/templates/base.html):

<html>
  <head>
    {% if title %}
    <title>{{title}} - microblog</title>
    {% else %}
    <title>microblog</title>
    {% endif %}
  </head>
  <body>
    <div>Microblog: <a href="/index">Home</a></div>
    <hr>
    {% with messages = get_flashed_messages() %}
    {% if messages %}
    <ul>
    {% for message in messages %}
        <li>{{ message }} </li>
    {% endfor %}
    </ul>
    {% endif %}
    {% endwith %}
    {% block content %}{% endblock %}
  </body>
</html>

Верю метод отображения сообщений не требует пояснений.

Иная новая функция, которую мы применяли в нашем представлении login — redirect. Эта функция перенаправляет клиентский веб-браузер на иную страницу, взамен запрашиваемой. В нашей функции представления мы применяли редирект на основную страницу, разработанную в предыдущих частях. Имейте в виду, что flash сообщения будут отображены даже если функция заканчивается перенаправлением.

Очаровательное время для того, Дабы запустить приложение и проверить как работают формы. Испробуйте отправить форму с пустым полем openid,Дабы увидеть как валидатор Required останавливает процесс передачи.

Совершенствование валидации полей

С приложением в его нынешнем состоянии, переданные с неверными данными формы не будут приняты. Взамен этого форма вновь будет отдана пользователю для исправления. Это именно то, что нам необходимо.

Что мы пропустили, так это уведомления пользователя о том, что именно не так с формой. К счастью, Flask-WTF также облегчает эту задачу.

Когда поле не проходит валидацию Flask-WTF добавляет наглядное сообщение об ошибке в объект формы. Эти сообщения доступны в образце, так что нам легко необходимо добавить немножко логики для их отображения.

Это наш образец login с сообщениями валидации полей (файл app/templates/login.html):

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<h1>Sign In</h1>
<form action="" method="post" name="login">
    {{form.hidden_tag()}}
    <p>
        Please enter your OpenID:<br>
        {{form.openid(size=80)}}<br>
        {% for error in form.errors.openid %}
        <span style="color: red;">[{{error}}]</span>
        {% endfor %}<br>
    </p>
    <p>{{form.remember_me}} Remember Me</p>
    <p><input type="submit" value="Sign In"></p>
</form>
{% endblock %}

Исключительное метаморфоза, которое мы сделали — добавили цикл, отрисовывающий всякие добавленные валидатором сообщения об ошибках справа от поля openid. Как правило, всякие поля имеющие прикрепленные валидаторы будут иметь ошибки, добавленные как form.errors.имя_поля. В нашем случае иы используемform.errors.openid. Мы отображаем эти сообщения в красном цвете, Дабы обратить на них внимание пользователя.

Взаимодействие с OpenID

На деле, мы будем сталкиваться с тем, что много людей даже не знают, что у них теснее есть парочка OpenID. Не слишком вестимо, что ряд больших подрядчиков служб в интернете поддерживает OpenID аутентификацию для их пользователей. Скажем, если у вас есть аккаунт в Google, то с ним у вас есть и OpenID. Так же как и в Yahoo, AOL, Flickr и множестве других сервисов.

Дабы облегчить пользователю вход на наш сайт с одним из Зачастую используемых OpenID, мы добавим ссылки на часть из них, Дабы пользователю не необходимо было вводить OpenID вручную.

Начнем с определения списка OpenID провайдеров, которых мы хотим представить. Мы можем сделать это в нашем файле конфигурации (файл config.py):

OPENID_PROVIDERS = [
    { 'name': 'Google', 'url': 'https://www.google.com/accounts/o8/id' },
    { 'name': 'Yahoo', 'url': 'https://me.yahoo.com' },
    { 'name': 'AOL', 'url': 'http://openid.aol.com/<username>' },
    { 'name': 'Flickr', 'url': 'http://www.flickr.com/<username>' },
    { 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]

Сейчас посмотрим как мы используем данный список в нашей функции представления login:

@app.route('/login', methods = ['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        flash('Login requested for OpenID="'   form.openid.data   '", remember_me='   str(form.remember_me.data))
        return redirect('/index')
    return render_template('login.html', 
        title = 'Sign In',
        form = form,
        providers = app.config['OPENID_PROVIDERS'])

Здесь мы получаем настройки путем их поиска по ключу в app.config. Дальше список добавляется в вызовrender_template как довод образца.

Как вы додумались, нам необходимо сделать еще один шаг, Дабы покончить с этим. Теперь нам необходимо указат как мы хотели бы отображать ссылки на этих провайдеров в нашем образце login (файл app/templates/login.html):

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<script type="text/javascript">
function set_openid(openid, pr)
{
    u = openid.search('<username>')
    if (u != -1) {
        // openid requires username
        user = prompt('Enter your '   pr   ' username:')
        openid = openid.substr(0, u)   user
}
    form = document.forms['login'];
    form.elements['openid'].value = openid
}
</script>
<h1>Sign In</h1>
<form action="" method="post" name="login">
    {{form.hidden_tag()}}
    <p>
        Please enter your OpenID, or select one of the providers below:<br>
        {{form.openid(size=80)}}
        {% for error in form.errors.openid %}
        <span style="color: red;">[{{error}}]</span>
        {% endfor %}<br>
        |{% for pr in providers %}
        <a href="javascript:set_openid('{{pr.url}}', '{{pr.name}}');">{{pr.name}}</a> |
        {% endfor %}
    </p>
    <p>{{form.remember_me}} Remember Me</p>
    <p><input type="submit" value="Sign In"></p>
</form>
{% endblock %}

Образец получился несколько длинным в связи со всеми этими изменениями. Некоторые OpenID включают в себя имена пользователей, для них у нас должно быть немножко javascript магии, которая запрашивает имя пользователя, а после этого создает OpenID. Когда пользователь кликает на ссылку OpenID провайдера и (опционально) вводит имя пользователя, OpenID для этого провайдера вставляется в текстовое поле.


скриншот нашей страницы входа позже нажатия на ссылку Google OpenID

Заключительные слова

Правда мы добились большого прогресса с нашими формами логина, в реальности мы не сделали ничего для входа пользователей в нашу систему. Все что мы сделали имело отношение к GUI процесса входа. Это потому, что раньше чем мы сумеем сделать настоящие логины, нам необходимо иметь базу данных, где мы можем записывать наших пользователей.

В дальнейшей части мы мы поднимем и запустим нашу базу данных, чуть позднее мы закончим нашу систему входа, так что следите за обновлениями следующих статей.

Приложение microblog в его нынешнем состоянии доступно для загрузки тут:
microblog-0.3.zip

Учтите, что zip файл не содержит в себе виртуального окружения flask. Сделайте его сами, следуя инструкциям в первой части, перед тем, как вы сумеете запустить приложение.

Если у вас есть какие-то вопросы либо комментарии, то вольно оставляйте их ниже.

Мигель

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB