Собственно для ознакомления с тем, как пишутся сайты на flask, я решил написать небольшую статейку.

Пользовать буду:

* Веб-фреймворк - Flask (http://flask.pocoo.org)

* База данных - mongodb (http://www.mongodb.org)

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

Для начала определимся таки с тем, что собой представляют наши веб фреймворк и база данных

Он собой представляет микрофреймворк, что значит, что в нем нет ничего лишнего (ок-ок, почти ничего лишнего).

Ну а есть в нем следующее:

* Шаблонизатор (jinja2)

* Маршрутизатор (werkzeug)

* Встроенный дебаггер (ценная штука)

* Ну и прочие небольшие плюшки.

Это документо-ориентированная база данных. Простая, надежная, с приятным языком запросов и абсолютно шикарным драйвером для Python (есть и для C, C#, Java, Ruby, etc.). Плюс хорошо работающие индексы, map/reduce на javascript и другие плюшки, включающие в себя отличную документацию (на английском, разумеется, языке).

Установка всего добра

Для начала качаем и ставим Python2.7 (flask пока не работает с python3). Потом ставим setuptools (он же easy_install), скачав его отсюда . Потом запускаем командную строку (консоль) и по очереди выполняем следующие комманды:

easy_install flask

easy_install flask-mongoengine

Все остальные зависимости подтянутся сами.

Теперь осталось поставить только mongodb. Раздобываем его , качая 32 или 64 разрядную версию соответственно. (В принципе подойдет любая, но у 32-разрядной есть ограничение на размер базы данных в 2 гигабайта)

Потом распаковываем её в директорию (для примера будет D:\mongodb\).

После этого снова возвращаемся к командной строке и делаем так:

mongod.exe --install --logpath "D:\mongodb\mongod.log" --dbpath=D:\mongodb\data\db

net start "Monog DB"

Теперь у вас есть сервис с именем Mongo DB, который запущен. Если захотите его убрать, то просто напишите в консоли вот это:

mongod.exe --remove

Всё, теперь, когда всё установлено, можно перейти к делу. Писать будем максимально просто и быстро, поэтому почти весь код будет в одном файле (да-да, я знаю, что это неправильно, но это же просто пример:), за исключением шаблонов.

Создаем структуру проекта

Создайте где-нибудь директорию "myblog". Уже внутри неё создайте директорию "templates", где будут жить не тужить наши шаблоны.

Всё, готово!

Кодим

Теперь открывайте свой любимый текстовый редактор (сойдет любой) и приступайте.

Для начала надо импортировать всё, что нам пригодится. Сделаем же это.

from flask import Flask, render_template, url_for, request

from flask.ext.mongoengine import MongoEngine

Создадим экземпляр нашего приложения!

app = Flask(__name__)

Затем впишем настройки базы данных и нашего приложения

app.config["MONGODB_DB"] = "myblog"

app.config["MONGODB_HOST"] = "127.0.0.1"

В директории templates лежит файл base.html - он представляет собой базу для всех остлаьных файлов. Они, грубо говоря, наследуются от него.

В нем определены два блока - title и content. Блоки определеять можно вообще в любом месте файла с помощью следующего нехитрого синтаксиса: {% block blockName %}{% endblock %}.

Чуть глубже, в директории posts лежат три файла (whoa!):

Все они весьма похожи друг на друга. Начинаются с одной строки - {% extends "base.html" %}, которая дает знать шаблонизатору, что шаблон этот расширяет base.html

Для того, чтобы писать в блок (title или content) используется всё тот же синтаксис {% block blockName %}тутваштекстиличтотамещё{% endblock %}. Можно определить новые блоки и ещё что-нибудь унаследовать уже от этого файла:)

Но это всё баловство. Как вы помните, вызывая код render_template, мы в качестве параметра (именованного) передавали ему либо список всех постов (в post_list), либо один конкретный пост (в post_detail). Давайте же посмотрим, что делает наш шаблонизатор с этими объектами.

Итак, глядим файл templates/posts/list.html

Что же там особенного? Да впрочем ничего, кроме того, что там есть такой кусочек:

Тут мы просто указываем для какой функции мы хотим получить ссылку (для post_detail) и что передаем ей в качестве параметра (slug = post.slug).

Всё. В templates/posts/detail.html ничего существенно нового вы не стретите, поскольку этот вариант блока скуп и прост.

А файл templates/posts/add.html сожержит только форму и ничего кроме формы.

Итак, что мы имеем в итоге?

В итоге имеем заготовку для блога. Куцую, но рабочую. В ней нет еще никакой системы авторизации, никаких красивостей, нет системы комментариев. Да вообще ничего нет, даже оформления нормального:). Зато всё свалено в одну кучу (кроме шаблонов, совесть же иметь надо:) и занимает очень мало строк (61).

Ах да, совсем забыл написать, как всё это дело запустить:

Снова идете к консоли (хаха, виндуксойды негодуют, линуксойды потирают крылья), переходите в директорию проекта и пишите "python main.py" (ну или заменяете main.py на ваше название файла.

Вуаля, всё должно заработать.

Переход в браузере по адресу http://127.0.0.1:5000/ вызовет пустую страницу с гордой надписью Posts list. Ничего страшного, идите на http://127.0.0.1:5000/posts/add/ и пробуйте добавлять посты.

Дальше, чтобы с этим можно было хоть что-то сделать, надо будет растащить это безобразие по отдельным файлам, прикрутить систему авторизации и комментарии, добавить админскую часть и пользовательские профили (может быть даже какую-нибудь oAuth авторизацию). Но это всё потом и не сразу.

Если интересно - пишите, что к этому чудовищу крутить в первую очередь. Постараюсь писать почаще:)

Спасибо за внимание.

Глава 9. JavaScript: баловство или необходимость?

Вопрос поставлен так не потому что автор книги что-то имеет против баловства. По некоторым поверьям весь наш мир есть не что иное, как баловство, мимолётная прихоть, игра какого-то могучего разума. Иногда в Сети можно встретить довольно любопытные вещи, написанные на JavaScript, - например, игру в тетрис. Но задачи нашей суровой и простой, как кирпич, книги требуют иного; сам стиль её требует освещения вопросов об html-скриптах с точки зрения пользы, удобства людей, просматривающих веб-страницы.

Самый главный скрипт

Наша борьба с таблицами в предыдущей главе вскрыла одну из важнейших проблем html-писателей: всё, что мы напишем, будет просматриваться пользователями не в идеальной среде, а на конкретных браузерах (от англ. browser - «браузер», обозреватель). То есть все спецификации - HMTL, CSS - это набор неких «усреднённых» правил, которые должны работать (являются рекомендациями). Но у разработчиков веб-обозревателей есть свои представления о том, как следует трактовать написанные нами html-тэги и правила CSS.

Поэтому любой веб-сайт, активно использующий на своих страницах CSS, обязательно вставляет на страницы скрипт, пытающийся определить, на каком браузере пользователь просматривает страницу. Однако и это не всегда решает проблему. Народ давно спорит о том, как именно следует определять тип браузера, потому что не все методы тут одинаково хороши, да ещё и некоторые браузеры пытаются зачем-то выдавать себя за другие (умышленно выдавать проверяющему скрипту неверную информацию).

Вот как можно получить информацию о браузере:

var agent = navigator.userAgent.toLowerCase(); document.write(agent);

Запишите этот код в файл browsr01.html (файл есть на CD в папке omne\js1, а также по адресу: omne/js1) и откройте файл в браузере. Интернет Эксплорер версии 5 напечатает на вашей странице следующую строчку:

mozilla/4.0 (compatible; msie 5.01; windows nt 5.0)

Браузер Mozilla Firefox - другую:

mozilla/5.0 (windows; u; windows nt 5.0; ru; rv:1.8) gecko/20051111 firefox/1.5

Мы смотрим на две разные строки и, анализируя их содержание, находим разницу. Примерно то же самое можно делать с помощью программы, написанной на JavaScript: надо специальной функцией проанализировать, распознать полученную строку, которую мы занесли в переменную agent. Эта функция (на самом деле не функция, а метод объекта String, но пока это неважно) называется indexOf() и используется так: Строка1.indexOf(Строка2). «Строка1» - строка, в которой надо найти последовательность символов; «Строка2» - последовательность символов, которую мы хотим найти в «Строке1». Важно подобрать правильное слово для поиска. Если мы для идентификации браузера будем искать, например, слово mozilla , то не сможем отличить IE от Firefox, потому что в обеих строчках искомое слово есть. Поэтому для опознания IE будем искать в названии браузера слово msie , а для опознания Firefox или SeaMonkey - слово gecko . Добавьте к первоначальному коду скрипта следующие строчки и сохраните новый текст в файле browsr02.html:

If (agent.indexOf("msie") > -1) document.write("
Internet Explorer"); if (agent.indexOf("gecko") > -1) document.write("
Gecko");

Попробуйте открыть файл browsr02.html в разных браузерах и посмотрите, что будет написано на странице.

Распознавание браузера необходимо не только для коррекции очень сложного веб-дизайна, но и для обычной, отнюдь не затейливой html-вёрстки (размещения текстов и картинок на странице). Разные браузеры могут отображать по-разному даже очень простой фрагмент. Допустим, мы решили заключить в рамку определённого размера один заголовок и один абзац из этой книги, и в предварительной отладке использовали Firefox. После несложной работы (результат - файлы browsr03.html и js1.css) мы в этом самом Firefox"е видим то, что хотели получить и успокаиваемся:

Глава 1. Создание вашей первой HTML-страницы

Потом мы (так, на всякий случай - ведь на странице не было ничего такого !) открываем тот же файл в Интернет Эксплорере, и вдруг видим, что наша простая вёрстка из двух абзацев куда-то «поехала»:

Глава 1. Создание вашей первой HTML- страницы

Что мешает вам создать веб-сайт и поместить его в Интернет? На этот вопрос можно найти довольно много ответов. Точнее, можно найти много причин, по которым создание интернет-страницы кажется вам невероятно сложной задачей.

Вроде и не очень большая беда - заголовок занял две строчки, текст абзаца немного сместился... Но чувствовать мы себя будем неуютно: получается, что мы не можем с уверенностью размещать материал на странице так, как нам надо; к тому же, если материала будет больше, вид страницы может измениться довольно существенно.

Наш фрагмент отображается в обозревателях по-разному, потому что Интернет Эксплорер считает ширину блочных элементов вместе с величиной padding и толщиной border , а Gecko (и Opera) исключают из размера блока padding и border . В стилевом файле js1.css мы задали ширину раздела div.b1 в 29em, а когда добавили к этому разделу рамку и отступы содержимого от краёв (padding), обозреватели Gecko оставили ширину полезной площади прежней - 29em и дорисовали отступы в 1em и рамку толщиной 0.4em вокруг раздела, увеличив тем самым его общую ширину на 2.8em. Интернет Эксплорер же втиснул рамку в заданную ширину 29em, чем фактически уменьшил ширину полезной площади на 2.8em. Вот строчки и «поехали»...

Дело, очевидно, можно исправить, увеличив ширину раздела div.b1 на ушедшие на рамку и padding 2.8em, то есть задав её в 31.8em. Тогда в IE заголовок уместится в одну строку, и остальной текст будет выглядеть, как задумано. Но в Gecko ширина раздела тоже увеличится на 2.8em (а она уже была нормальной) - и строчки опять «поползут». Вот примерно для таких случаев и существует решение - с помощью скрипта привязывать к странице разные CSS-файлы, в зависимости от типа браузера. Создайте новый стилевой файл js2.css с точно таким же содержимым, что и в js1.css, затем измените в нём ширину раздела div.b1 с 29em на 31.8em. Добавьте также в файле js1.css (для обозревателей Gecko) к правилам для body font-size :16px - таково в IE значение размера шрифта по умолчанию, такой же размер должен быть и в других браузерах (значение по умолчанию в них не совпадает со значением в IE). Затем создайте новый файл browsr04.html с точно таким же содержимым, как в browsr03.html, и переделайте скрипт в файле browsr04.html на следующий:

var agent = navigator.userAgent.toLowerCase(); if (agent.indexOf("gecko") > -1) document.write(""); if (agent.indexOf("msie") > -1) document.write(""); else document.write("");

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

Как это работает

Скрипт - это, скорее, жаргонное название, по-научному его обычно называют «сценарием» (от англ. script - «сценарий»). Так вот, скрипт начинает работать по той же причине, по которой расставленные вами html-тэги и записанные правила CSS превращаются в видимые глазом изменения шрифта и цвета страницы. Эта причина - браузер: когда программа просмотра интернет-страниц находит в html-тексте метку , она (программа) делает на экране абзацный отступ по правилам, найденным ею в соответствующем файле CSS. Когда браузер находит в тексте html-страницы метки ..., всё, что находится между этими метками, он рассматривает как команды, написанные на языке JavaScript, и пытается эти команды выполнить.

Например, если мы запишем в html-текст (между соответствующими обозначениями начала и конца скрипта) команду скрипта document.write(«Привет!»), браузер при открытии документа выведет на экран слово «Привет!».

Так же можно заставить браузер вставить в текст страницы невидимую глазом запись , привязывающую к странице файл CSS. Эта запись получается невидимой по самой своей природе: браузеры обучены рассматривать текст, заключённый в тэге , как определённую инструкцию, не предназначенную для вывода на экран. Невидимая на экране команда JavaScript вставляет в текст страницы невидимую глазом инструкцию - и вид страницы изменяется. Всё просто.

Красота решения

На языках HMTL, JavaScript, так же, как и на русском языке, можно описать одни и те же предметы по-разному. Мы не планируем в этой книге вдаваться в стилистические тонкости, поэтому понятие «по-разному» попытаемся конкретизировать, сузить. Мы будем считать, что разные решения возникают, в основном, от борьбы двух тенденций, двух не всегда осознаваемых устремлений человека: 1) экономия мыслительных усилий; 2) экономия материала. Например, у меня в голове (или в душе?) такая борьба началась в тот самый момент, как я написал для этой книги скрипт, позволяющий менять оформление страницы в зависимости от браузера.

Сам скрипт я написал очень быстро (потому что издатель торопил с текстом книги). Но потом меня стала мучить совесть, и я решил, не смотря на спешку, всё-таки скрипт немного усовершенствовать. То есть укоротить. Потому что в спешке думать было особо некогда, и пришлось, из экономии мыслительных усилий, писать «простым», внешне очевидным, но не самым оптимальным способом.

Если посмотреть на текст скрипта из файла browsr04.html повнимательней, можно заметить, что строчка «document.write("");» повторяется в нём три раза почти без изменений. Отличаются эти три строки только одной цифрой в имени файла: js1.css - js2.css. Возникает вопрос: нельзя ли эту строчку записать только один раз, в конце скрипта, а цифру представить каким-нибудь хитрым образом, чтобы она прямо при записи менялась в зависимости от обстоятельств. Ответ: на то и существуют переменные.

Объявим в начале нашего скрипта с помощью волшебного слова var переменную i :

var i; (каждое «действие» в сценарии JavaScript должно заканчиваться знаком; - точка с запятой).

Самую последнюю строчку, печатающую результат в файл, сделаем такой:

Document.write("");

Знак + в данном случае соединяет в единую строку несколько разных фрагментов текста. Если бы мы, например, написали строку «2 + 2», JavaScript заставил бы браузер вывести на экран «4» (а не «22»). Но мы записываем "js" + 2 + ".css", и получим в итоге "js2.css". Обратите внимание на то, как расставлены кавычки. Все текстовые строки в JavaScript должны быть заключены в кавычки - всё равно, в какие: двойные или одинарные. Мы выбрали двойные. Но в результирующей строке языка HTML тоже нужны кавычки, и если мы попытаемся написать "document.write("