TurboGears — Обзор
Web Application Framework или просто Web Framework представляет собой набор библиотек и модулей, который позволяет разработчику веб-приложений писать приложения, не заботясь о деталях низкого уровня, таких как протоколы, управление потоками и т. Д.
Что такое TurboGears?
TurboGears — это фреймворк для веб-приложений, написанный на Python. Первоначально созданная Kevin Dangoor в 2005 году, ее последняя версия TurboGears (версия 2.3.7) управляется группой разработчиков во главе с Марком Раммом и Флораном Аиде.
TurboGears следует парадигме Model-View-Controller, как и большинство современных веб-фреймворков, таких как Rails, Django, Struts и т. Д.
Контроллер модельного вида
MVC — это шаблон проектирования программного обеспечения для разработки веб-приложений. Модель контроллера представления модели состоит из трех частей:
-
Модель — самый низкий уровень шаблона отвечает за ведение данных.
-
Просмотр — это ответственность за отображение всех или части данных для пользователя.
-
Контроллер — программный код, который контролирует взаимодействие между моделью и представлением.
Модель — самый низкий уровень шаблона отвечает за ведение данных.
Просмотр — это ответственность за отображение всех или части данных для пользователя.
Контроллер — программный код, который контролирует взаимодействие между моделью и представлением.
MVC популярен, поскольку он изолирует логику приложения от уровня пользовательского интерфейса и поддерживает разделение задач. Здесь Контроллер получает все запросы для приложения и затем работает с Моделью, чтобы подготовить любые данные, необходимые для Представления. Затем представление использует данные, подготовленные контроллером, для генерации окончательного презентабельного ответа. Абстракция MVC может быть графически представлена следующим образом:
Модель
Модель отвечает за управление данными приложения. Он отвечает на запрос от представления и также отвечает на инструкции от контроллера, чтобы обновить себя.
Вид
Представление данных в определенном формате, инициированное решением контроллера о представлении данных. Это основанные на сценариях системы шаблонов, которые очень легко интегрировать с технологией AJAX.
Контроллер
Контроллер отвечает за ответ на пользовательский ввод и выполнение взаимодействий с объектами модели данных. Контроллер получает входные данные, он проверяет входные данные, а затем выполняет бизнес-операцию, которая изменяет состояние модели данных.
TurboGears построен на основе ряда библиотек и инструментов. Эти инструменты были изменены в разных версиях TurboGears. Компоненты текущей версии (версия 2.3.7) перечислены ниже.
SQLAlchemy
Это набор SQL с открытым исходным кодом, который обеспечивает сопоставление отношений объектов (ORM) для кода Python.
Genshi
Этот шаблонизатор используется для создания внешнего интерфейса приложений TG. Система веб-шаблонов объединяет шаблон с определенным источником данных для отображения динамических веб-страниц.
ToscaWidgets
Это библиотека виджетов для генерации HTML-форм с серверными элементами управления. Tosca также выступает в качестве промежуточного программного обеспечения для связи с виджетами JavaScript и наборами инструментов.
коробка передач
Он предоставляет набор команд для управления проектами и серверными приложениями TurboGears. Приложения TurboGears могут быть развернуты на любом веб-сервере, совместимом с WSGI.
Интерфейс шлюза веб-сервера (WSGI) был принят в качестве стандарта для разработки веб-приложений на Python. WSGI — это спецификация универсального интерфейса между веб-сервером и веб-приложениями. Пакет wsgiref является эталонной реализацией WSGI. Он используется для добавления поддержки WSGI в веб-фреймворк TurboGears. Модуль simple_server в этом пакете реализует простой HTTP-сервер, который обслуживает приложения WSGI. Мы будем использовать его для тестирования приложений, разработанных в этом уроке.
TurboGears — Окружающая среда
необходимое условие
Python 2.6 или выше. Более ранние версии TurboGears не были совместимы с Python 3.X. Последняя версия утверждает, что хорошо работает на Python 3.X. Однако официальная документация TurboGears по-прежнему основана на среде Python 2.7.
Следующая команда устанавливает virtualenv —
pip install virtualenv
Эта команда нуждается в правах администратора . Добавьте sudo перед pip в Linux / Mac OS. Если вы работаете в Windows, войдите как Администратор. На Ubuntu virtualenv может быть установлен с помощью менеджера пакетов.
Sudo apt-get install virtualenv
После установки новая виртуальная среда создается в папке.
mkdir newproj cd newproj virtualenv venv
Чтобы активировать соответствующую среду, в Linux / OS X
venv/bin/activate
в Windows
venv\scripts\activate
Теперь мы готовы установить TurboGears в этой среде. Минимальная установка TurboGears выполняется с помощью следующей команды —
pip install TurboGears2
Вышеуказанная команда может быть запущена напрямую без виртуальной среды для общесистемной установки.
Чтобы установить TurboGears вместе со средствами разработки, используйте следующую команду —
pip install tg.devtools
TurboGears — Первая программа
TurboGears имеет минимальный режим, который позволяет быстро создавать приложения с одним файлом. Простые примеры и сервисы могут быть построены быстро с минимальным набором зависимостей.
Класс приложения в приложении TG наследуется от класса TGController . Методы в этом классе доступны для доступа @expose декоратором из модуля tg . В нашем первом приложении метод index () отображается как корень нашего приложения. Класс TGController также необходимо импортировать из модуля tg .
from tg import expose, TGController class MyController(TGController): @expose() def index(self): return 'Hello World turbogears'
Затем установите конфигурацию приложения и объявите объект приложения. Здесь конструктор класса AppConfig принимает два параметра — минимальный атрибут со значением true и класс контроллера.
config = AppConfig(minimal = True, root_controller = RootController()) application = config.make_wsgi_app()
Функция make_wsgi_app () здесь создает объект приложения.
Чтобы обслуживать это приложение, нам нужно запустить HTTP-сервер. Как упоминалось ранее, мы будем использовать модуль simple_server в пакете wsgiref для его настройки и запуска. Этот модуль имеет метод make_server (), который требует номер порта и объект приложения в качестве аргументов.
from wsgiref.simple_server import make_server server = make_server('', 8080, application) server.serve_forever()
Это означает, что наше приложение будет обслуживаться через порт 8080 локального хоста.
Ниже приведен полный код нашего первого приложения TurboGears —
app.py
from wsgiref.simple_server import make_server from tg import expose, TGController, AppConfig class MyController(TGController): @expose() def index(self): return 'Hello World TurboGears' config = AppConfig(minimal = True, root_controller = MyController()) application = config.make_wsgi_app() print "Serving on port 8080..." server = make_server('', 8080, application) server.serve_forever()
Запустите приведенный выше скрипт из оболочки Python.
Python app.py
Введите http: // localhost: 8080 в адресной строке браузера, чтобы просмотреть сообщение «Hello World TurboGears».
В tg.devtools TurboGears есть коробка передач. Это набор команд, которые полезны для управления более сложными проектами TG. Проекты с полным стеком можно быстро создать с помощью следующей команды Gearbox —
gearbox quickstart HelloWorld
Это создаст проект под названием HelloWorld .
TurboGears — Зависимости
Проект TurboGears содержит следующие каталоги —
-
Конфиг — Где находится настройка проекта и конфигурация
-
Контроллеры — все контроллеры проекта, логика веб-приложения
-
i018n — файлы переводов для поддерживаемых языков
-
Lib — служебные функции и классы Python
-
Модель — База данных моделей
-
Общедоступные статические файлы — CSS, JavaScript и изображения
-
Шаблоны — Шаблоны, предоставляемые нашими контролерами.
-
Тесты — набор тестов сделано.
-
Websetup — функции, выполняемые при настройке приложения.
Конфиг — Где находится настройка проекта и конфигурация
Контроллеры — все контроллеры проекта, логика веб-приложения
i018n — файлы переводов для поддерживаемых языков
Lib — служебные функции и классы Python
Модель — База данных моделей
Общедоступные статические файлы — CSS, JavaScript и изображения
Шаблоны — Шаблоны, предоставляемые нашими контролерами.
Тесты — набор тестов сделано.
Websetup — функции, выполняемые при настройке приложения.
Как установить проект
Этот проект теперь должен быть установлен. Файл setup.py уже предоставлен в базовом каталоге проекта. Зависимости проекта устанавливаются при выполнении этого скрипта.
Python setup.py develop
По умолчанию следующие зависимости устанавливаются во время настройки проекта:
- мензурка
- Genshi
- zope.sqlalchemy
- SQLAlchemy
- перегонный куб
- repoze.who
- tw2.forms
- tgext.admin ≥ 0.6.1
- WebHelpers2
- галдеж
После установки начните обслуживать проект на сервере разработки, введя следующую команду в оболочке —
Gearbox serve –reload –debug
Следуйте вышеупомянутой команде, чтобы служить готовым примером проекта. Откройте http: // localhost: 8080 в браузере. Этот готовый пример приложения дает краткое представление о самой платформе TurboGears.
В этом проекте Hello контроллер по умолчанию создается в каталоге контроллеров как Hello / hello / controllers.root.py . Давайте изменим root.py с помощью следующего кода —
from hello.lib.base import BaseController from tg import expose, flash class RootController(BaseController): movie = MovieController() @expose() def index(self): return "<h1>Hello World</h1>" @expose() def _default(self, *args, **kw): return "This page is not ready"
Когда основное рабочее приложение готово, в класс контроллера можно добавить больше представлений. В приведенном выше классе Mycontroller добавлен новый метод sayHello () . Декоратор @expose () присоединяет к нему URL-адрес / sayHello . Эта функция предназначена для принятия имени в качестве параметра из URL.
После запуска сервера с помощью команды «gearbox serve» http: // localhost: 8080 . Сообщение Hello World будет отображаться в браузере, даже если введены следующие URL —
HTTP: // локальный: 8080 /
HTTP: // локальный: 8080 / индекс
Все эти URL-адреса сопоставлены с методом RootController.index () . Этот класс также имеет метод _default (), который будет вызываться всякий раз, когда URL-адрес не сопоставлен с какой-либо конкретной функцией. Ответ на URL отображается на функцию декоратором @expose ().
С помощью URL можно отправить параметр в открытую функцию. Следующая функция читает параметр имени из URL.
@expose() def sayHello(self, name): return '<h3>Hello %s</h3>' %name
Следующий вывод будет отображаться в браузере как ответ на URL — http: // localhost: 8080 /? Name = MVL
Hello MVL
TurboGears автоматически сопоставляет параметры URL с аргументами функции. Наш класс RootController унаследован от BaseController. Это определяется как base.py в папке lib приложения.
Его код следующий:
from tg import TGController, tmpl_context from tg import request __all__ = ['BaseController'] def __call__(self, environ, context): tmpl_context.identity = request.identity return TGController.__call__(self, environ, context)
TGController .__ call__ отправляет методу Controller, на который направляется запрос.
TurboGears — Шаблоны обслуживания
Событие, хотя HTML-содержимое может быть возвращено в браузер, для более сложного вывода всегда предпочтительнее использовать механизм шаблонов. В полномасштабном проекте, «быстро запущенном» с помощью коробки передач, Genshi включен как средство визуализации шаблонов по умолчанию. Однако в минимальном приложении необходимо установить и включить Genshi (или любой другой шаблонизатор, например, jinja). Механизм шаблонов Genshi позволяет писать шаблоны в чистом формате xhtml и проверяет их, чтобы обнаружить проблемы во время компиляции и предотвратить обслуживание неработающих страниц.
На шаблоны ссылаются с помощью точечной нотации. В нашем проекте Hello имеется каталог шаблонов для хранения веб-страниц шаблонов. Следовательно, sample.html будет называться hello.templates.sample (расширение не указано). TurboGears визуализирует этот шаблон через декоратор экспозиции, чтобы связать с ним метод контроллера с помощью функции tg.render_template () .
Открытая функция контроллера возвращает объект словаря Python. Этот объект словаря в свою очередь передается связанному шаблону. Заполнители в шаблоне заполняются значениями словаря.
Для начала давайте отобразим веб-страницу с простым HTML-скриптом. Открытый контроллер возвращает пустой словарный объект, поскольку мы не собираемся отправлять какие-либо данные для анализа в HTML-сценарии.
Как создать образец HTML
Наш sample.html приведен ниже. Убедитесь, что он хранится в каталоге шаблонов проекта.
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h2>Hello, Welcome to TurboGears!.</h2> </body> </html>
Добавьте функцию sample () в root.py и выставьте через нее sample.html.
@expose("hello.templates.sample") def sample(self): return {}
Следующий результат будет отображаться в браузере при вводе URL-адреса http: // localhost: 8080 / sample после запуска веб-сервера.
Как уже упоминалось выше, объект словаря отправляется в виде набора параметров в шаблон Genshi. Этот шаблон содержит «заполнители», которые динамически заполняются параметрами, полученными от контроллера.
Давайте изменим функцию sample () для отправки объекта словаря в шаблон примера.
@expose("hello.templates.sample") def sample(self,name): mydata = {'person':name} return mydata
Создайте sample.html в папке с шаблонами ( templates \ sample.html )
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h2>Hello, my name is ${person}!.</h2> </body> </html>
В приведенном выше HTML-коде $ {person} является заполнителем. Введите http: // localhost: 8080 / sample? Name = MVL в качестве URL-адреса в браузере. Этот URL-адрес сопоставлен с методом sample () в нашем корневом контроллере. Возвращает объект словаря. Это выбирается связанной страницей шаблона sample.html в каталоге шаблонов. Затем $ {person} заменяется MVL на веб-странице.
Также возможно получить доступ к данным формы HTML в функции контроллера. Форма HTML использует для отправки данных формы.
TurboGears — методы HTTP
Протокол Http является основой передачи данных во всемирной паутине. В этом протоколе определены различные методы извлечения данных из указанного URL. В следующей таблице приведены различные методы http —
Sr.No. | Методы и описание HTTP |
---|---|
1 |
ПОЛУЧИТЬ Отправляет данные в незашифрованном виде на сервер. Самый распространенный метод. |
2 |
ГОЛОВА То же, что GET, но без тела ответа |
3 |
СООБЩЕНИЕ Используется для отправки данных формы HTML на сервер. Данные, полученные методом POST, не кэшируются сервером. |
4 |
ПОЛОЖИЛ Заменяет все текущие представления целевого ресурса на загруженный контент. |
5 |
УДАЛЯТЬ Удаляет все текущие представления целевого ресурса, заданного URL |
ПОЛУЧИТЬ
Отправляет данные в незашифрованном виде на сервер. Самый распространенный метод.
ГОЛОВА
То же, что GET, но без тела ответа
СООБЩЕНИЕ
Используется для отправки данных формы HTML на сервер. Данные, полученные методом POST, не кэшируются сервером.
ПОЛОЖИЛ
Заменяет все текущие представления целевого ресурса на загруженный контент.
УДАЛЯТЬ
Удаляет все текущие представления целевого ресурса, заданного URL
Создание формы HTML
Давайте создадим форму HTML и отправим данные формы на URL. Сохраните следующий скрипт как login.html
<html> <body> <form action = "http://localhost:8080/login" method = "get"> <p>Enter Name:</p> <p><input type = "text" name = "nm" /></p> <p><input type = "submit" value = "submit" /></p> </form> </body> </html>
Данные, введенные в этой форме, должны быть отправлены на URL / login . Теперь создайте функцию контроллера loginpage () и откройте для него вышеуказанную html-страницу.
@expose("hello.templates.login") def loginpage(self): return {}
Чтобы получить данные формы, предоставьте контроллер login () , который имеет атрибуты формы в качестве своих параметров. Здесь «nm» — имя поля ввода текста в форме входа в систему, то же самое используется в качестве параметра функции login ().
@expose("hello.templates.sample") def login(self, nm): name = nm return {'person':name}
Как видно, данные, полученные из формы входа, отправляются в шаблон sample.html (использовался ранее). Он анализируется механизмом шаблонов Genshi для генерации следующего вывода:
Метод POST
Когда форма HTML использует метод POST для отправки данных на URL-адрес в атрибуте действия, данные формы не отображаются в URL-адресе. Закодированные данные принимаются в качестве аргумента dict функцией контроллера. Аргумент ** kw ниже — это объект словаря, содержащий данные.
HTML-форма содержит два поля ввода текста.
<html> <body> <form action = "http://localhost:8080/marks" method = "post"> <p>Marks in Physics:</p> <p><input type = "text" name = "phy" /></p> <p>Marks in Maths:</p> <p><input type = "text" name = "maths" /></p> <p><input type = "submit" value = "submit" /></p> </form> </body> </html>
Контроллер marks () получает данные формы и отправляет их в шаблон sample.html . Код для root.py выглядит следующим образом —
from hello.lib.base import BaseController from tg import expose, request class RootController(BaseController): @expose("hello.templates.marks") def marksform(self): return {} @expose("hello.templates.sample") def marks(self, **kw): phy = kw['phy'] maths = kw['maths'] ttl = int(phy)+int(maths) mydata = {'phy':phy, 'maths':maths, 'total':ttl} return mydata
Наконец, шаблон sample.html выглядит следующим образом:
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h2>Hello, Welcome to TurboGears!.</h2> <h3>Marks in Physics: ${phy}.</h3> <h3>Marks in Maths: ${maths}.</h3> <h3>Total Marks: ${total}</h3> </body> </html>
Запустите сервер (если он еще не запущен)
Gearbox server –reload –debug
Введите http: // localhost :: 8080 / marksform в браузере
Sample.html отобразит следующий вывод —
TurboGears — Genshi Template Language
Genshi — это язык шаблонов на основе XML. Он похож на Kid , который раньше был движком шаблонов для более ранних версий TurboGears. Genshi и Kid вдохновлены другими известными языками шаблонов, такими как HSLT, TAL и PHP .
Шаблон Genshi состоит из директив обработки. Эти директивы являются элементами и атрибутами в шаблоне. Директивы Genshi определены в пространстве имен http://genshi.edgewall.org/ . Следовательно, это пространство имен должно быть объявлено в корневом элементе шаблона.
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> ... </html>
Объявление выше означает, что пространство имен по умолчанию установлено в XHTML, а директивы Genshi имеют префикс «py».
Директивы Генши
Ряд директив определен в Genshi. Следующий список перечисляет директивы Genshi —
- ру: если
- ру: выбрать
- ру: для
- р: Защита
- ру: матч
- ру: с
- ру: заменить
- ру: содержание
- ру: ATTRS
- ру: полоса
Условные разделы
Genshi предоставляет две директивы для условного рендеринга контента — py: if и py: select.
ру: если
Содержимое элемента этой директивы будет отображено, только если выражение в условии if оценивается как true. Предполагая, что данные в контексте шаблона: {‘foo’: True, ‘bar’: ‘Hello’} , следующая директива —
<div> <b py:if = "foo">${bar}</b> </div>
приведет к
Hello
Однако этот вывод не будет отображаться, если для ‘foo’ установлено значение False .
Эта директива также может быть использована в качестве элемента. В этом случае <py: if> должен быть закрыт соответствующим </ py: if>
<div> <py:if test = "foo"> <b>${bar}</b> </py:if> </div>
ру: выбрать
Расширенная условная обработка возможна с использованием py: выбрать в сочетании с директивами py: when и py: else. Эта функция похожа на конструкцию switch-case в C / C ++ .
Выражение в py: директива Choose проверяется с различными значениями, идентифицированными с py: когда будут отображаться альтернативы и соответствующее содержимое. Альтернатива по умолчанию может быть предоставлена в форме директивы py: else.
<div py:choose = "foo”> <span py:when = "0">0</span> <span py:when = "1">1</span> <span py:otherwise = "">2</span> </div>
Следующий пример иллюстрирует использование py: choose и py: when директив. HTML-форма отправляет данные на / mark URL. Функция marks () перенаправляет метки и результаты в виде объекта словаря в шаблон total.html . Условное отображение результата Pass / Fail достигается использованием директив py: choose и py: when .
HTML-скрипт ввода отметок ( marks.html ) выглядит следующим образом:
<html> <body> <form action = "http://localhost:8080/marks" method = "post"> <p>Marks in Physics:</p> <p><input type = "text" name = "phy" /></p> <p>Marks in Maths:</p> <p><input type = "text" name = "maths" /></p> <p><input type = "submit" value = "submit" /></p> </form> </body> </html>
Полный код root.py выглядит следующим образом. Контроллер marks () отправляет оценки и результат в шаблон total.html —
from hello.lib.base import BaseController from tg import expose, request class RootController(BaseController): @expose("hello.templates.marks") def marksform(self): return {} @expose("hello.templates.total") def marks(self, **kw): phy = kw['phy'] maths = kw['maths'] ttl = int(phy)+int(maths) avg = ttl/2 if avg ≥ 50: mydata = {'phy':phy, 'maths':maths, 'total':ttl, 'result':2} else: mydata = {'phy':phy, 'maths':maths, 'total':ttl,'result':1} return mydata
Total.html в папке шаблонов получает данные словаря и условно анализирует их в выводе html следующим образом:
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <head> <title>TurboGears Templating Example</title> </head> <body> <h2>Hello, Welcome to TurboGears!.</h2> <h3>Marks in Physics: ${phy}.</h3> <h3>Marks in Maths: ${maths}.</h3> <h3>Total Marks: ${total}</h3> <div py:choose = "result"> <span py:when = "1"><h2>Result: Fail</h2></span> <span py:when = "2"><h2>Result: Pass</h2></span> </div> </body> </html>
Запустите сервер (если он еще не запущен)
Gearbox server –reload –debug
Введите http: // localhost :: 8080 / marksform в браузере —
Total.html будет отображать следующий вывод —
ру: для
Элемент в директиве py: for повторяется для каждого элемента итерируемого объекта, обычно объекта списка Python. Если items = [1,2,3] присутствует в контексте шаблона, его можно повторить с помощью следующей py: for директива —
<ul> <li py:for = "item in items">${item}</li> </ul>
Будет получен следующий вывод —
1 2 3
В следующем примере показаны данные формы HTML, представленные в шаблоне total.html с использованием директивы py: for, также можно использовать следующим образом:
<py:for each = "item in items"> <li>${item}</li> </py:for>
HTML Form Script
<html> <body> <form action = "http://localhost:8080/loop" method="post"> <p>Marks in Physics:</p> <p><input type = "text" name = "phy" /></p> <p>Marks in Chemistry:</p> <p><input type = "text" name = "che" /></p> <p>Marks in Maths:</p> <p><input type = "text" name = "maths" /></p> <p><input type = "submit" value = "submit" /></p> </form> </body> </html>
Контроллер loop () считывает данные формы и отправляет их в total.template в форме объекта списка.
from hello.lib.base import BaseController from tg import expose, request class RootController(BaseController): @expose("hello.templates.marks") def marksform(self): return {} @expose("hello.templates.temp") def loop(self, **kw): phy = kw['phy'] maths = kw['maths'] che = kw['che'] l1 = [] l1.append(phy) l1.append(che) l1.append(maths) return ({'subjects':['physics', 'Chemistry', 'Mathematics'], 'marks':l1})
Шаблон temp.html использует цикл py: for для отображения содержимого объекта dict в форме таблицы.
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <body> <b>Marks Statement</b> <table border = '1'> <thead> <py:for each = "key in subjects"><th>${key}</th></py:for> </thead> <tr> <py:for each = "key in marks"><td>${key}</td></py:for> </tr> </table> </body> </html>
Запустите сервер (если он еще не запущен)
gearbox server –reload –debug
Введите http: // localhost :: 8080 / marksform в браузере.
При отправке вышеуказанной формы в браузере будет отображаться следующий вывод.
р: Защита
Эта директива используется для создания макроса. Макрос — это многократно используемый фрагмент кода шаблона. Как и функция Python, она имеет имя и может иметь параметры. Вывод этого макроса может быть вставлен в любое место шаблона.
Директива py: def имеет следующий синтаксис:
<p py:def = "greeting(name)"> Hello, ${name}! </p>
Этот макрос может быть представлен с помощью значения переменной параметра name.
${greeting('world')} ${greeting('everybody)}
Эта директива также может использоваться с другой версией синтаксиса следующим образом:
<py:def function = "greeting(name)"> <p>Hello, ${name}! </p> </py:def>
В следующем примере контроллер macro () в root.py отправляет объект dict с двумя ключами name1 и name2 в шаблон macro.html.
from hello.lib.base import BaseController from tg import expose, request class RootController(BaseController): @expose('hello.templates.macro') def macro(self): return {'name1':'TutorialPoint', 'name2':'TurboGears'}
Этот шаблон macro.html содержит определение макроса, называемого приветствием. Он используется для генерации приветственного сообщения для данных, полученных от контроллера.
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <body> <h2>py:def example</h2> <div> <div py:def = "greeting(name)"> Hello, Welcome to ${name}! </div> <b> ${greeting(name1)} ${greeting(name2)} </b> </div> </body> </html>
Запустите сервер, используя коробку передач
gearbox serve –reload –debug
Вызовите контроллер macro (), введя следующий URL в браузере —
HTTP: // локальный: 8080 / макро
Следующий вывод будет отображен в браузере —
ру: с
Эта директива позволяет вам присваивать выражения локальным переменным. Эти локальные переменные делают выражение внутри менее многословным и более эффективным.
Предполагая, что x = 50 задано в данных контекста для шаблона, следующая будет py: with директива —
<div> <span py:with = "y = 50; z = x+y">$x $y $z</span> </div>
Это приведет к следующему выводу —
50 50 100
Также доступна альтернативная версия для py: with —
<div> <py:with = "y = 50; z = x+y">$x $y $z</py:with> </div>
В следующем примере контроллер macro () возвращает объект dict с ключами name, phy и maths.
from hello.lib.base import BaseController from tg import expose, request class RootController(BaseController): @expose('hello.templates.macro') def macro(self): return {'name':'XYZ', 'phy':60, 'maths':70}
Шаблон macro.html добавляет значения ключей phy и maths с помощью директивы py: with.
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <body> <h2>py:with example</h2> <h3>Marks Statement for : ${name}!</h3> <b>Phy: $phy Maths: $maths <span py:with = "ttl = phy+maths">Total: $ttl</span> </b> </body> </html>
Браузер отобразит следующий вывод в ответ на URL http: // localhost: 8080 / macro
Директивы по манипулированию структурой
Директива py: attrs добавляет, изменяет или удаляет атрибуты элемента.
<ul> <li py:attrs = "foo">Bar</li> </ul>
Если foo = {‘class’: ‘collapse’} присутствует в контексте шаблона, который будет представлен вышеупомянутым фрагментом.
<ul> <li class = "collapse">Bar</li> </ul>
Директива py: content заменяет любой вложенный контент результатом вычисления выражения —
<ul> <li py:content = "bar">Hello</li> </ul>
Если в контекстных данных указать bar = ‘Bye’, это приведет к
<ul> <li>Bye</li> </ul>
Директива py: replace заменяет сам элемент на результат вычисления выражения —
<div> <span py:replace = "bar">Hello</span> </div>
Если в контекстных данных задано значение bar = ‘Bye’,
<div> Bye </div>
TurboGears — Включает
Содержимое другого XML-документа (особенно HTML-документа) можно включить с помощью тегов включения в текущем документе. Чтобы включить такое включение, пространство имен XInclude должно быть объявлено в корневом элементе HTML-документа.
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:xi = "http://www.w3.org/2001/XInclude >
Приведенное выше объявление указывает, что директива include содержит префикс «xi» . Чтобы добавить содержимое другой html-страницы в текущий документ, используйте директиву xi: include следующим образом:
<xi:include href = "somepage.html" />
В следующем примере root.py содержит контроллер include (), который предоставляет include.html.
from hello.lib.base import BaseController from tg import expose, request class RootController(BaseController): @expose('hello.templates.include') def include(self): return {}
HTML заголовка и нижнего колонтитула
В include.html объявлено пространство имен include и добавлено содержимое heading.html и footer.html. Вот HTML-скрипт шаблонов \ include.html —
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:xi = "http://www.w3.org/2001/XInclude"> <head> <title>TurboGears Templating Example</title> </head> <body> <xi:include href = "heading.html" /> <h2>main content </h2> <xi:include href = "footer.html" /> </body> </html>
Вот код шаблонов \ heading.html —
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h1>This is page Header</h1> </body> </html>
Ниже приведены шаблоны \ footer.html
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h3>This is page footer</h3> </body> </html>
Запустите разработку с помощью редуктора и введите http: // localhost: 8080 / include в браузере. Вывод будет выглядеть так, как показано ниже —
Таким образом, модульная конструкция видов может быть достигнута. Если ресурс, упомянутый в директиве xi: include, недоступен, возникнет ошибка. В таком случае альтернативный ресурс может быть загружен с использованием xi: fallback.
<xi:include href = “main.html”> <xi:fallback href = ”default.html”/> </xi.include>
Включение содержимого может быть сделано динамическим как атрибут href, который может содержать выражения.
Добавьте следующий контроллер в root.py.
@expose('hello.templates.ref-include') def refinclude(self): return {'pages':['heading','main','footer']}
Сохраните следующий код как ref-include.html в папке шаблонов.
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" xmlns:xi = "http://www.w3.org/2001/XInclude"> <head> <title>TurboGears Templating Example</title> </head> <body> <xi:include href = "${name}.html" py:for = "name in pages" /> </body> </html>
Перед запуском сервера убедитесь, что в папке templates находятся heading.html, main.html и footer.html. Введите http: // localhost: 8082 / refinclude в браузере, чтобы получить следующий вывод
TurboGears — рендеринг JSON
Декоратор @expose () по умолчанию отображает HTML-контент. Однако это может быть установлено в тип контента json . TurboGears поддерживает рендеринг json с помощью класса tg.jsonify.JSONEncoder ( ** kwargs ) . Для рендеринга данных json просто передайте json как тип контента, чтобы выставить декоратор.
@expose('json') def jsondata(self, **kwargs): return dict(hello = 'World')
Если в браузере введен URL ‘/ jsondata’, он ответит, показывая —
{"hello": "World"}
рендеринг jsonp
JSONP означает JSON с отступом. Он работает аналогично выводу json, за исключением того факта, что он предоставляет ответ application / javascript с вызовом функции javascript, предоставляющей все значения, возвращаемые контроллером в качестве аргументов функции.
Чтобы включить рендеринг jsonp, вы должны сначала добавить его в список необходимых движков внутри вашего приложения — config / app_cfg.py —
base_config.renderers.append('jsonp')
Напишите ваш выставленный декоратор следующим образом —
@expose('json') @expose('jsonp') def jsonpdata (self, **kwargs): return dict(hello = 'World')
При доступе к / jsonpdata? Callback = callme вы должны увидеть —
callme({"hello": "World"});
TurboGears — иерархия URL
Иногда веб-приложению может потребоваться структура URL, имеющая более одного уровня. TurboGears может просматривать иерархию объектов, чтобы найти подходящий метод, который может обработать ваш запрос.
Проект, «быстро запущенный» с коробкой передач, имеет класс BaseController в папке lib проекта. Он доступен как «Hello / hello / lib / base.py». Он служит базовым классом для всех субконтроллеров. Чтобы добавить подуровень URL в приложение, спроектируйте подкласс BlogController, производный от BaseController.
Этот BlogController имеет две функции контроллера, index () и post (). Оба предназначены для представления шаблона каждый, blog.html и post.html.
Примечание. Эти шаблоны помещаются во вложенную папку — templates / blog
class BlogController(BaseController): @expose('hello.templates.blog.blog') def index(self): return {} @expose('hello.templates.blog.post') def post(self): from datetime import date now = date.today().strftime("%d-%m-%y") return {'date':now}
Теперь объявите объект этого класса в классе RootController (в root.py) следующим образом:
class RootController(BaseController): blog = BlogController()
Другие функции контроллера для URL верхнего уровня будут присутствовать в этом классе, как и ранее.
Когда введен URL-адрес http: // localhost: 8080 / blog / , он будет сопоставлен с функцией контроллера index () внутри класса BlogController. Аналогично, http: // localhost: 8080 / blog / post вызовет функцию post ().
Код для blog.html и post.html приведен ниже.
Blog.html <html> <body> <h2>My Blog</h2> </body> </html> post.html <html> <body> <h2>My new post dated $date</h2> </body> </html>
Когда введен URL http: // localhost: 8080 / blog / , он выдаст следующий вывод:
Когда введен URL http: // localhost: 8080 / blog / post , он выдаст следующий результат:
TurboGears — ToscaWidgets Forms
Одним из наиболее важных аспектов любого веб-приложения является представление пользовательского интерфейса для пользователя. HTML предоставляет тег <form>, который используется для разработки интерфейса. Элементы формы, такие как ввод текста, радио, выбор и т. Д. Могут быть использованы соответствующим образом. Данные, введенные пользователем, передаются в виде сообщения Http-запроса на серверный скрипт методом GET или POST.
Серверный скрипт должен воссоздавать элементы формы из данных http-запроса. Таким образом, в этом случае элементы формы должны быть определены дважды — один раз в HTML и снова в сценарии на стороне сервера.
Еще одним недостатком использования формы HTML является то, что трудно (если не невозможно) визуализировать элементы формы динамически. HTML сам по себе не позволяет проверять вводимые пользователем данные.
ToscaWidgets2
TurboGears использует ToscaWidgets2, гибкую библиотеку для рендеринга и проверки форм. Используя ToscaWidgets, мы можем определить поля формы в нашем скрипте Python и отобразить их, используя шаблон HTML. Также возможно применить проверку к полю tw2.
Библиотека ToscaWidgets представляет собой набор из множества модулей. Некоторые важные модули перечислены ниже —
-
tw2.core — обеспечивает базовую функциональность. Виджеты в этом модуле не предназначены для конечного пользователя.
-
tw2.forms — это базовая библиотека форм. Он содержит виджеты для полей, наборов полей и форм.
-
tw2.dynforms — содержит функциональность динамических форм.
-
tw2.sqla — это интерфейс для базы данных SQLAlchemy.
tw2.core — обеспечивает базовую функциональность. Виджеты в этом модуле не предназначены для конечного пользователя.
tw2.forms — это базовая библиотека форм. Он содержит виджеты для полей, наборов полей и форм.
tw2.dynforms — содержит функциональность динамических форм.
tw2.sqla — это интерфейс для базы данных SQLAlchemy.
tw2.forms
Он содержит класс Form, который служит основой для пользовательских форм. Существует класс TableForm, который полезен для визуализации полей в таблице с двумя столбцами. ListForm представляет свои поля в неупорядоченном списке.
Sr.No. | Поля и описание |
---|---|
1 |
Текстовое поле Однострочное поле ввода текста |
2 |
TextArea Многострочное поле ввода текста |
3 |
CheckBox Представлен прямоугольный флажок с надписью |
4 |
CheckBoxList Множественные флажки группы pf |
5 |
Переключатель Кнопка переключения для выбора / отмены выбора |
6 |
RadioButtonList Группа взаимоисключающих Радио кнопок |
7 |
PasswordField Аналогично текстовому полю, но клавиши ввода не отображаются |
8 |
CalendarDatePicker Позволяет пользователю выбрать дату |
9 |
SubmitButton Кнопка для отправки формы |
10 |
ImageButton Кликабельная кнопка с изображением сверху |
11 |
SingleSelectField Позволяет выбрать один элемент из списка |
12 |
MultipleSelectField Позволяет выбрать несколько элементов из списка |
13 |
FileField Поле для загрузки файла |
14 |
EmailField Поле ввода электронной почты |
15 |
URLField Поле ввода для ввода URL |
16 |
NumberField Спинбокс номер |
17 |
RangeField Ползунок номера |
Текстовое поле
Однострочное поле ввода текста
TextArea
Многострочное поле ввода текста
CheckBox
Представлен прямоугольный флажок с надписью
CheckBoxList
Множественные флажки группы pf
Переключатель
Кнопка переключения для выбора / отмены выбора
RadioButtonList
Группа взаимоисключающих Радио кнопок
PasswordField
Аналогично текстовому полю, но клавиши ввода не отображаются
CalendarDatePicker
Позволяет пользователю выбрать дату
SubmitButton
Кнопка для отправки формы
ImageButton
Кликабельная кнопка с изображением сверху
SingleSelectField
Позволяет выбрать один элемент из списка
MultipleSelectField
Позволяет выбрать несколько элементов из списка
FileField
Поле для загрузки файла
EmailField
Поле ввода электронной почты
URLField
Поле ввода для ввода URL
NumberField
Спинбокс номер
RangeField
Ползунок номера
В следующем примере создается форма с использованием некоторых из этих виджетов. Хотя большинство этих виджетов определены в tw2.forms, CalendarDateField определен в модуле tw2.Dynforms. Следовательно, оба этих модуля вместе с tw2.core импортируются в начале —
import tw2.core as twc import tw2.forms as twf import tw2.dynforms as twd
Форма ToscaWidgets — это класс, производный от базового класса tw2.forms.form . Требуемые виджеты размещаются внутри объекта Layout. В этом примере используется TableLayout . Виджеты отображаются в виде таблицы с двумя столбцами. Первый столбец показывает заголовок, а второй столбец показывает поле ввода или выбора.
Объект TextField создается с использованием следующего конструктора —
twf.TextField(size, value = None)
Если не указано, объект TextField принимает размер по умолчанию и изначально пуст. При объявлении объекта TextArea можно указать количество строк и столбцов.
twf.TextArea("",rows = 5, cols = 30)
Объект NumberField — это TextField, который может принимать только цифры. Стрелки вверх и вниз генерируются на правой границе, чтобы увеличить или уменьшить число внутри нее. Начальное значение также может быть указано в качестве аргумента в конструкторе.
twf.NumberField(value)
Справа от поля CalendarDatePicker отображается кнопка календаря. При нажатии появляется селектор даты. Пользователь может вручную ввести дату в поле или выбрать из селектора даты.
twd.CalendarDatePicker()
Объект EmailField представляет TextField, но текст в нем должен быть в формате электронной почты.
EmailID = twf.EmailField()
Следующая форма также имеет RadioButtonList. Конструктор этого класса содержит объект List в качестве значения параметра options. Радиокнопка для каждого параметра будет отображаться. Выбор по умолчанию указывается параметром value.
twf.RadioButtonList(options = ["option1","option2"],value = option1)
CheckBoxList отображает флажки для каждой опции в списке.
twf.CheckBoxList(options = [option1, option2, option3])
В этой библиотеке ToscaWidgets раскрывающийся список называется полем SingleSelect. Элементы в объекте List, соответствующие параметру options, формируют выпадающий список. Видимый заголовок устанавливается как значение параметра prompt_text.
twf.SingleSelectField(prompt_text = 'text', options=['item1', 'item2', 'item3'])
По умолчанию в форме отображается кнопка «Отправить» с надписью «сохранить». Чтобы отобразить другой заголовок, создайте объект SubmitButton и укажите его в качестве параметра значения.
twf.SubmitButton(value = 'Submit')
Форма отправляется по URL-адресу, который указывается в качестве значения параметра действия формы. По умолчанию данные формы отправляются методом http POST.
action = 'URL'
В следующем коде форма с именем AdmissionForm разработана с использованием описанных выше виджетов. Добавьте этот код в root.py перед классом RootController.
class AdmissionForm(twf.Form): class child(twf.TableLayout): NameOfStudent = twf.TextField(size = 20) AddressForCorrespondance = twf.TextArea("", rows = 5, cols = 30) PINCODE = twf.NumberField(value = 431602) DateOfBirth = twd.CalendarDatePicker() EmailID = twf.EmailField() Gender = twf.RadioButtonList(options = ["Male","Female"],value = 'Male') Subjects = twf.CheckBoxList(options = ['TurboGears', 'Flask', 'Django', 'Pyramid']) MediumOfInstruction = twf.SingleSelectField(prompt_text = 'choose', options = ['English', 'Hindi', 'Marathi', 'Telugu']) action = '/save_form' submit = twf.SubmitButton(value ='Submit')
Теперь сохраните этот код ниже как twform.html в каталоге шаблонов —
<!DOCTYPE html> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <head> <title>TurboGears Form Example</title> </head> <body> <div id = "tw form"> ${form.display(value = dict(title = 'default title'))} </div> </body> </html>
В классе RootController (в root.py) добавьте следующую функцию контроллера —
@expose('hello.templates.twform') def twform(self, *args, **kw): return dict(page = 'twform', form = MovieForm)
В классе AdmissionForm мы указали / save_form как URL действия. Следовательно, добавьте функцию save_form () в RootController.
@expose() def save_movie(self, **kw): return str(kw)
Убедитесь, что сервер работает (с помощью коробки передач). Введите http: // localhost: 8080 / twform в браузере.
Нажатие кнопки « Отправить» отправит эти данные в URL save_form () , который отобразит данные формы в виде объекта словаря.
{ 'EmailID': u'[email protected]', 'NameOfStudent': u'Malhar Lathkar', 'Gender': u'Male', 'PINCODE': u'431602', 'DateOfBirth': u'2015-12-29', 'Subjects': [u'TurboGears', u'Flask', u'Django'], 'MediumOfInstruction': u'', 'AddressForCorrespondance': u'Shivaji Nagar\r\nNanded\r\nMaharashtra' }
TurboGears — Валидация
Хорошая библиотека виджетов Forms должна иметь функцию проверки ввода. Например, пользователь должен быть вынужден ввести данные в обязательное поле или проверить, содержит ли поле электронной почты действительный адрес электронной почты, не прибегая к каким-либо другим программным средствам (таким как функция JavaScript) для проверки.
Ранние версии библиотеки форм ToscaWidgets использовались модулем FormEncode для поддержки проверки. ToscaWidgets2 теперь имеет встроенную поддержку проверки, доступную в модуле tw2.core. Тем не менее, все еще возможно использовать методы проверки FormEncode.
Для проверки формы ToscaWidgets используется @validate decorator.
@validate(form, error_handler, validators)
-
«Форма» — это объект формы ToscaWidgets, подлежащий проверке.
-
«Обработчик ошибок» — это метод контроллера, используемый для обработки ошибок формы.
-
«Валидаторы» — это объект словаря, содержащий валидаторы FormEncode.
«Форма» — это объект формы ToscaWidgets, подлежащий проверке.
«Обработчик ошибок» — это метод контроллера, используемый для обработки ошибок формы.
«Валидаторы» — это объект словаря, содержащий валидаторы FormEncode.
Типы валидаторов
Модуль tw2.core содержит класс валидатора, от которого наследуются другие валидаторы. Также возможно разработать собственный валидатор на его основе. Некоторые из важных валидаторов описаны ниже —
LengthValidator — Проверьте, имеет ли значение заданную длину. Минимальные и максимальные пределы определяются параметрами min и max. Пользовательские сообщения для длины ниже и выше мин и макс можно указать как параметр tooshort и toolong.
tw2.core.LengthValidator(min = minval, max = maxval, msgs = { 'tooshort': (‘message for short length’), 'toolong': (‘message for long length)})
RangeValidator — обычно используется вместе с RangeField. Это полезно для проверки значения числового поля в пределах минимального и максимального пределов. Сообщения для параметров tooshort и toolong могут быть настроены.
tw2.core.RangeValidator(min = minval, max = maxval, msgs = { 'tooshort': (‘message for short length’), 'toolong': (‘message for long length)})
IntValidator — этот класс является производным от RangeValidator. Обычно это используется для проверки, если ввод в обычном текстовом поле содержит целочисленные данные. Минимальные и максимальные пределы, а также сообщения об ошибках могут быть установлены. Кроме того, сообщение об ошибке для нецелочисленного ввода может быть указано как параметр notint.
tw2.core.IntValidator(msgs = {‘notint’:’Must be Integer’})
OneOfValidator — этот валидатор заставляет пользователя выбирать значение из доступных опций только в списке.
tw2.core.OneOfValidator(values = [option1, option2,..], msgs = {‘notinlist’:’Not in List’}}
DateValidator — очень полезно, чтобы гарантировать, что пользовательский ввод является действительной датой. Формат даты (по умолчанию YMD) и сообщение об ошибке настраиваются. Минимальные и максимальные пределы даты также могут быть указаны. DateTimeValidator также доступен для проверки объекта класса DateTime.
tw2.core.DateValidator(msgs = {format = ’%Y-%m-%d’, 'baddatetime': ('baddate', ('Must follow date format $format_str'))}
EmailValidator — проверяет ввод пользователя по действительному адресу электронной почты. Этот класс унаследован от более общего RegexValidator.
tw2.core.EmailValidator(msgs = {'badregex': ('bademail', ('Must be a valid email address')) }
UrlValidator — этот класс также унаследован от RegexValidator. Он проверяет вводимые пользователем данные для действительного URL.
tw2.core.UrlValidator(msgs = {'badregex': ('badurl', ('Must be a valid URL’)) }
MatchValidator — подтверждает, сопоставлено ли значение одного поля с другим. Это особенно полезно, когда пользователь должен выбрать и подтвердить поле пароля. Типичное использование MatchValidator показано ниже —
import tw2.core as twc import tw2.forms as twf class AdmissionForm(twf.Form): class child(twf.TableLayout): validator = twc.MatchValidator('pw', 'pwconfirm') pw = twf.PasswordField() pwconfirm = twf.PasswordField()
Также возможно построить составной валидатор, где валидация должна быть успешной, если какая-либо из проверок пройдена. В других случаях вы можете захотеть, чтобы проверка прошла успешно, только если входные данные прошли все проверки. Для этого tw2.core предоставляет валидаторы Any и All, которые являются подклассами расширяемого CompoundValidator.
TurboGears — Flash сообщения
TurboGears предоставляет очень удобную систему обмена сообщениями для уведомления пользователя в ненавязчивой форме. Класс TGFlash в модуле tg обеспечивает поддержку перепрошивки сообщений, которые хранятся в обычном cookie. Этот класс поддерживает выбор флэш-сообщений на стороне сервера, а также на стороне клиента через JavaScript.
Метод render () класса TGFlash, когда используется из самого Python, может быть вызван из шаблона для визуализации флеш-сообщения. Если используется на JavaScript, он предоставляет объект WebFlash. Он предоставляет методы payload () и render () для извлечения текущего флеш-сообщения и его рендеринга из JavaScript.
Когда проект TurboGears создается с помощью «быстрого старта», он имеет шаблон Master.html. Он содержит определение переменной этого flash-объекта. Содержимое этого флеш-сообщения, полученного от контроллера, заменяет отмеченный заполнитель в этом шаблоне.
<py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)"> <div py:if = "flash" py:replace = "Markup(flash)" /> </py:with>
Tg.flash_obj — это объект WebFlash, который доступен внутри любого отрендеренного шаблона, включая шаблон master.html . Этот объект позволяет получить текущее флэш-сообщение и отобразить его.
Flash-сообщения хранятся в файле cookie (имя которого по умолчанию — webflash) с помощью метода tg.flash () . Сообщение и параметры состояния затем передаются ему.
tg.flash('Message', 'status')
Если метод, называемый flash, выполняет перенаправление, тогда flash будет виден внутри перенаправленной страницы. Если метод непосредственно предоставляет шаблон, то флэш-память будет видна внутри самого шаблона.
Внешний вид флеш-сообщения можно настроить, применив стиль CSS к коду состояния. «Быстрый старт» проекта содержит коды ошибок, предупреждений, информации и статуса ok, настроенные таблицей стилей public / css / style.css. Также можно добавить больше кодов состояния со стилями.
#flash > .warning { color: #c09853; background-color: #fcf8e3; border-color: #fbeed5; } #flash > .ok { color: #468847; background-color: #dff0d8; border-color: #d6e9c6; } #flash > .error { color: #b94a48; background-color: #f2dede; border-color: #eed3d7; } #flash > .info { color: #3a87ad; background-color: #d9edf7; border-color: #bce8f1; }
Эта внешняя таблица стилей должна быть включена в шаблон —
<link rel = "stylesheet" type = "text/css" media = "screen" href = "${tg.url('/css/style.css')}" />
Конфигурирование любой поддержки сообщений Flash может быть достигнуто путем установки параметров для метода configure () объекта TGFlash или в файле app_cfg.py (в папке config). Настраиваемые параметры:
Sr.No. | Параметры и описание |
---|---|
1 |
flash.cookie_name Имя файла cookie, используемого для хранения флеш-сообщений. По умолчанию используется webflash . |
2 |
flash.default_status Статус сообщения по умолчанию, если не указан (по умолчанию нормально) |
3 |
flash.template Используется как флэш-шаблон при визуализации. |
4 |
flash.allow_html Включает / выключает экранирование во флеш-сообщениях , по умолчанию HTML не разрешен. |
5 |
flash.js_call Код JavaScript, который будет запускаться при отображении flash из JavaScript. По умолчанию используется webflash.render () |
6 |
flash.js_template Экземпляр string.Template используется для замены полной поддержки JavaScript для флеш-сообщений. |
flash.cookie_name
Имя файла cookie, используемого для хранения флеш-сообщений. По умолчанию используется webflash .
flash.default_status
Статус сообщения по умолчанию, если не указан (по умолчанию нормально)
flash.template
Используется как флэш-шаблон при визуализации.
flash.allow_html
Включает / выключает экранирование во флеш-сообщениях , по умолчанию HTML не разрешен.
flash.js_call
Код JavaScript, который будет запускаться при отображении flash из JavaScript. По умолчанию используется webflash.render ()
flash.js_template
Экземпляр string.Template используется для замены полной поддержки JavaScript для флеш-сообщений.
-
pop_payload () — функция выбирает текущее флэш-сообщение, статус и связанную информацию. Получение флеш-сообщения приведет к удалению куки.
-
render (container_id, use_js = True) — визуализировать флеш-сообщение внутри шаблона или обеспечить поддержку Javascript для них.
-
container_id — это DIV, в котором будут отображаться сообщения, а use_js переключается между рендерингом флэш-памяти в формате HTML или для использования JavaScript.
-
status — Получить только текущее состояние Flash, получение статуса Flash удалит cookie.
-
сообщение — Получить только текущее флеш-сообщение, получение флеш-сообщения приведет к удалению куки.
pop_payload () — функция выбирает текущее флэш-сообщение, статус и связанную информацию. Получение флеш-сообщения приведет к удалению куки.
render (container_id, use_js = True) — визуализировать флеш-сообщение внутри шаблона или обеспечить поддержку Javascript для них.
container_id — это DIV, в котором будут отображаться сообщения, а use_js переключается между рендерингом флэш-памяти в формате HTML или для использования JavaScript.
status — Получить только текущее состояние Flash, получение статуса Flash удалит cookie.
сообщение — Получить только текущее флеш-сообщение, получение флеш-сообщения приведет к удалению куки.
Как сделать простое флеш сообщение?
В следующем примере метод flash () предоставляется в классе корневого контроллера. Вызывает сообщение flash (), которое отображается в предоставленном шаблоне flash.html.
from hello.lib.base import BaseController from tg import expose, flash, redirect, request class RootController(BaseController): @expose('hello.templates.flash') def flash(self, user = None): if user: flash(message = "Welcome "+user,status = "ok") else: flash(message = "Welcome Guest",status = "info") return {}
Код для создания flash.html в папке с шаблонами выглядит следующим образом
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" xmlns:xi = "http://www.w3.org/2001/XInclude"> <head> <title>TurboGears 2.3: Flash messages>/title> <link rel = "stylesheet" type = "text/css" media = "screen" href = "${tg.url('/css/style.css')}" /> <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)"> <div py:if = "flash" py:replace = "Markup(flash)" /> </py:with> </head> <body> <h2>Hello TurboGears</h2> </body> </html>
Запустите сервер и введите в браузере http: // localhost: 8080 / flash? User = MVL
Измените URL-адрес на http: // localhost: 8080 / flash и просмотрите флэш-сообщение, отформатированное в соответствии с определением в style.css
TurboGears — Cookies & Sessions
Часто требуется хранить данные простого просмотра, прикрепленные к браузеру пользователя. Сессии являются наиболее часто используемой техникой. Сеанс представляет данные, которые не нужно хранить в более постоянной форме, такой как файл на диске или база данных.
Однако данные сеанса в TurboGears могут быть поддержаны файловой системой, базой данных или хешированными значениями cookie. Небольшое количество данных сеанса обычно хранится в файлах cookie, но для большего объема данных сеанса используется MemCache.
MemCache — это демон системного уровня. Он обеспечивает быстрый доступ к кэшированным данным и чрезвычайно масштабируем. Однако он предназначен для использования только на защищенных серверах и, следовательно, должен поддерживаться и защищаться сисадмином.
Стакан в управлении сессиями
TurboGears использует Beaker для управления сессиями. Проект, запущенный с помощью коробки передач, по умолчанию настроен на использование хешированных файлов cookie для хранения данных сеанса.
Каждый раз, когда клиент подключается, промежуточное программное обеспечение сеанса (Beaker) будет проверять файл cookie, используя имя файла cookie, которое было определено в файле конфигурации. Если cookie не найден, он будет установлен в браузере. При всех последующих посещениях промежуточное программное обеспечение будет находить cookie и использовать его.
Чтобы включить управление сеансом, класс сеанса должен быть включен в проект, следуя инструкции import —
from tg import session
Чтобы сохранить данные в переменной сеанса —
session[‘key’] = value session.save()
Чтобы получить переменную сеанса —
return session[‘key’]
Обратите внимание, что вам нужно явно сохранить сеанс, чтобы ваши ключи были сохранены в этом сеансе.
Метод delete () объекта сеанса удалит все сеансы пользователя —
session.delete()
Даже если не принято удалять все пользовательские сеансы в любой производственной среде, вы обычно делаете это для очистки после выполнения юзабилити или функциональных тестов.
Ниже приведен простой пример демонстрации сессий. Класс RootController имеет метод setsession (), который устанавливает переменную сеанса.
from hello.lib.base import BaseController from tg import expose, session class RootController(BaseController): @expose() def setsession(self): session['user'] = 'MVL' session.save() str = "<b>sessionVariable set to "+session['user'] str = str+"<br><a href = '/getsession'>click here to retrieve</a></b>" return str @expose() def getsession(self): return "<b>value of session variable retrieved " +session['user'] +"</b>"
Введите http: // localhost: 8080 / setsession
Ссылка в браузере ведет на http: // localhost: 8080 / getsession, который извлекает и отображает переменную сеанса —
TurboGears — Кэширование
Для повышения производительности веб-приложения, особенно если оно задействовано в длительных операциях, используются методы кэширования. TurboGears предоставляет два типа методов кэширования —
Кеширование целых страниц
Он работает на уровне протокола HTTP, чтобы избежать полных запросов к серверу, поскольку браузер пользователя или промежуточный прокси-сервер (например, Squid) перехватывают запрос и возвращают кэшированную копию файла.
Кэширование на уровне приложения
Это работает на сервере приложений, чтобы кэшировать вычисленные значения, часто результаты сложных запросов к базе данных, так что будущие запросы могут избежать необходимости пересчитывать значения. Для веб-приложений кэширование на уровне приложений обеспечивает гибкий способ кэширования результатов сложных запросов, так что общая загрузка данного метода контроллера может быть уменьшена до нескольких пользовательских или конкретных запросов и накладных расходов на рендеринг шаблона. ,
Кэширование на уровне приложения
Как упоминалось ранее, проект «быстрого запуска» TurboGears настроен на включение пакета Beaker для поддержки кэширования. Beaker поддерживает следующие бэкэнды, используемые для хранения кеша:
-
память — используется для хранения на процесс. Это очень быстро.
-
файловая система — для каждого процесса хранения, а также многопроцессорные.
-
База данных DBM — для каждого процесса, многопроцессная, довольно быстрая.
-
База данных SQLAlchemy — хранилище для каждой базы данных на сервере. Более медленный по сравнению с приведенными выше вариантами.
-
Memcached — многосерверный кеш на основе памяти.
память — используется для хранения на процесс. Это очень быстро.
файловая система — для каждого процесса хранения, а также многопроцессорные.
База данных DBM — для каждого процесса, многопроцессная, довольно быстрая.
База данных SQLAlchemy — хранилище для каждой базы данных на сервере. Более медленный по сравнению с приведенными выше вариантами.
Memcached — многосерверный кеш на основе памяти.
Кэширование контроллера
Для быстрого кэширования контроллера доступен декоратор cached () . Все тело контроллера кэшируется в зависимости от различных параметров запроса. Определение декоратора tg.decorators.cached () следующее
tg.decorators.cached(key, expire, type, query-args, cache_headers, invalidate_on_startup, cache_response)
Описание параметров выглядит следующим образом —
Sr.No. | Параметры и описание |
---|---|
1 |
ключ Определяет параметры контроллера, используемые для генерации ключа кэша. |
2 |
истекать Время в секундах до истечения срока действия кэша. По умолчанию «никогда». |
3 |
Тип dbm, память, файл, memcached или None. |
4 |
cache_headers Кортеж имен заголовков, указывающих заголовки ответа. |
5 |
invalidate_on_startup Если True, кеш становится недействительным каждый раз, когда приложение запускается или перезапускается. |
6 |
cache_response ответ должен быть кэширован или нет, по умолчанию True. |
ключ
Определяет параметры контроллера, используемые для генерации ключа кэша.
истекать
Время в секундах до истечения срока действия кэша. По умолчанию «никогда».
Тип
dbm, память, файл, memcached или None.
cache_headers
Кортеж имен заголовков, указывающих заголовки ответа.
invalidate_on_startup
Если True, кеш становится недействительным каждый раз, когда приложение запускается или перезапускается.
cache_response
ответ должен быть кэширован или нет, по умолчанию True.
Ниже приведен пример кэширования контроллера:
@cached(expire = 100, type = 'memory') @expose() def simple(self): return "This is a cached controller!"
Кэширование на уровне шаблона
Механизм шаблонов Genshi извлекает шаблон из кэша, если его содержимое не изменилось. Размер этого кэша по умолчанию — 25. По умолчанию автоматическая перезагрузка шаблонов имеет значение true. Чтобы повысить производительность, в app_cfg.py можно сделать следующие настройки:
[app:main] genshi.max_cache_size = 100 auto_reload_templates = false
Чтобы кэшировать шаблон, вам просто нужно вернуть параметр tg_cache из контроллера, который отображает кэшированный шаблон.
Tg_cache — это словарь, который принимает следующие ключи:
-
ключ — ключ кеша. По умолчанию: нет.
-
expire — как долго кэш должен оставаться в живых. По умолчанию: никогда не истекает
-
тип — память, дбм, memcached. По умолчанию: дБм.
ключ — ключ кеша. По умолчанию: нет.
expire — как долго кэш должен оставаться в живых. По умолчанию: никогда не истекает
тип — память, дбм, memcached. По умолчанию: дБм.
Следующий пример иллюстрирует кеширование шаблона:
@expose(hello.templates.user') def user(self, username): return dict(user = username, tg_cache = dict(key = user, expire = 900))
TurboGears — SQLAlchemy
Хотя можно использовать SQL в приложении TurboGears для выполнения операций CRUD с любой реляционной базой данных, рекомендуется использовать SQLAlchemy, набор инструментов Python — это мощный инструмент сопоставления объектов, который дает разработчикам приложений полную мощь и гибкость SQL. В дополнение к поддержке баз данных на основе SQL через SQLAlchemy, TurboGears также поддерживает базу данных MongoDB через Ming. В этом разделе обсуждается функциональность SQLAlchemy.
Что такое ORM (объектно-реляционное сопоставление)?
Большинство платформ языка программирования являются объектно-ориентированными. С другой стороны, данные на серверах РСУБД хранятся в виде таблиц. Сопоставление объектных отношений — это метод сопоставления параметров объекта с базовой структурой таблицы СУБД. API ORM предоставляет методы для выполнения операций CRUD без необходимости писать необработанные операторы SQL.
Когда проект TurboGears создается с помощью команды «быстрый старт» из набора инструментов коробки передач, поддержка SQLAlchemy по умолчанию включается следующими параметрами конфигурации:
config['use_sqlalchemy'] = True config['sqlalchemy.url'] = 'sqlite:///devdata.db'
«Быстрый старт» проекта также создает пакет моделей внутри него. Например, у проекта «Hello» будет Hello \ hello \ model. Следующие файлы создаются в этом пакете —
-
__init__.py — здесь настраивается доступ к базе данных. Объекты модели приложения импортируются в этот модуль. Он также имеет DBSession — глобальный менеджер сеансов, а также DeclarativeBase, который является базовым классом для всех классов моделей.
-
auth.py — здесь определяются модели, используемые стеком аутентификации. Дополнительные модели базы данных хранятся в этом пакете как отдельный модуль и добавляются в файл __init__.py.
__init__.py — здесь настраивается доступ к базе данных. Объекты модели приложения импортируются в этот модуль. Он также имеет DBSession — глобальный менеджер сеансов, а также DeclarativeBase, который является базовым классом для всех классов моделей.
auth.py — здесь определяются модели, используемые стеком аутентификации. Дополнительные модели базы данных хранятся в этом пакете как отдельный модуль и добавляются в файл __init__.py.
TurboGears — Создание моделей
Давайте добавим модель студента, которая настроит таблицу студента в нашей базе данных sqlite .
Привет \ привет \ модель \ student.py
from sqlalchemy import * from sqlalchemy.orm import mapper, relation, relation, backref from sqlalchemy import Table, ForeignKey, Column from sqlalchemy.types import Integer, Unicode, DateTime from hello.model import DeclarativeBase, metadata, DBSession from datetime import datetime class student(DeclarativeBase): __tablename__ = 'student' uid = Column(Integer, primary_key = True) name = Column(Unicode(20), nullable = False, default = '') city = Column(Unicode(20), nullable = False, default = '') address = Column(Unicode(100), nullable = False, default = '') pincode = Column(Unicode(10), nullable = False, default = '')
Теперь добавьте эту модель в функцию init_model () внутри __init__.py. Эта функция уже содержит в себе модель аутентификации. Добавьте нашу модель студента ниже.
# Import your model modules here. from hello.model.auth import User, Group, Permission from hello.model.student import student
Если вы хотите, чтобы таблица была инициализирована с некоторыми данными во время настройки моделей, добавьте ее в bootstrap.py в пакете websetup. Добавьте следующие операторы в функцию bootstrap () .
s1 = model.student() s1.name = 'M.V.Lathkar' s1.city = 'Nanded' s1.address = 'Shivaji Nagar' s1.pincode = '431602' model.DBSession.add(s1) model.DBSession.flush() transaction.commit()
Модели инициализируются с помощью команды setup-app на коробке передач —
gearbox setup-app
Объект сеанса SQLAlchemy управляет всеми операциями сохранения объекта ORM.
TurboGears — CRUD-операции
Следующие методы сеанса выполняют операции CRUD —
-
DBSession.add (объект модели) — вставляет запись в отображаемую таблицу.
-
DBSession.delete (объект модели) — удаляет запись из таблицы.
-
DBSession.query (model) .all () — извлекает все записи из таблицы (соответствует запросу SELECT).
DBSession.add (объект модели) — вставляет запись в отображаемую таблицу.
DBSession.delete (объект модели) — удаляет запись из таблицы.
DBSession.query (model) .all () — извлекает все записи из таблицы (соответствует запросу SELECT).
Вы можете применить фильтр к полученному набору записей, используя атрибут фильтра. Например, чтобы получить записи с city = ‘Hyderabad’ в таблице студентов, используйте следующий оператор —
DBSession.query(model.student).filter_by(city = ’Hyderabad’).all()
Теперь мы увидим, как взаимодействовать с моделями через URL контроллера.
Сначала давайте разработаем форму ToscaWidgets для ввода данных учащегося
Привет \ привет \ controllers.studentform.py
import tw2.core as twc import tw2.forms as twf class StudentForm(twf.Form): class child(twf.TableLayout): name = twf.TextField(size = 20) city = twf.TextField() address = twf.TextArea("",rows = 5, cols = 30) pincode = twf.NumberField() action = '/save_record' submit = twf.SubmitButton(value = 'Submit')
В RootController (root.py приложения Hello) добавьте следующую функцию, отображающую URL «/ add» —
from hello.controllers.studentform import StudentForm class RootController(BaseController): @expose('hello.templates.studentform') def add(self, *args, **kw): return dict(page='studentform', form = StudentForm)
Сохраните следующий HTML-код как studentform.html в папке шаблонов —
<!DOCTYPE html> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <head> <title>Student Registration Form</title> </head> <body> <div id = "getting_started"> ${form.display(value = dict(title = 'Enter data'))} </div> </body> </html>
Введите http: // localhost: 8080 / add в браузере после запуска сервера. Следующая информация о студентах откроется в браузере —
Приведенная выше форма предназначена для отправки по URL — адресу ‘/ save_record’ . Следовательно, необходимо добавить функцию save_record () в root.py, чтобы открыть ее. Данные из формы Student получены этой функцией как объект dict () . Он используется для добавления новой записи в таблицу учеников, лежащую в основе модели ученика.
@expose() #@validate(form = AdmissionForm, error_handler = index1) def save_record(self, **kw): newstudent = student(name = kw['name'],city = kw['city'], address = kw['address'], pincode = kw['pincode']) DBSession.add(newstudent) flash(message = "new entry added successfully") redirect("/listrec")
Обратите внимание, что после успешного добавления браузер будет перенаправлен на URL-адрес «/ listrec» . Этот URL предоставляется функцией listrec () . Эта функция выбирает все записи в таблице студентов и отправляет их в виде объекта dict в шаблон studentlist.html. Эта функция listrec () выглядит следующим образом:
@expose ("hello.templates.studentlist") def listrec(self): entries = DBSession.query(student).all() return dict(entries = entries)
Шаблон studentlist.html выполняет итерацию по объекту словаря записей с использованием директивы py: for. Шаблон studentlist.html выглядит следующим образом:
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/"> <head> <link rel = "stylesheet" type = "text/css" media = "screen" href = "${tg.url('/css/style.css')}" /> <title>Welcome to TurboGears</title> </head> <body> <h1>Welcome to TurboGears</h1> <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)"> <div py:if = "flash" py:replace = "Markup(flash)" /> </py:with> <h2>Current Entries</h2> <table border = '1'> <thead> <tr> <th>Name</th> <th>City</th> <th>Address</th> <th>Pincode</th> </tr> </thead> <tbody> <py:for each = "entry in entries"> <tr> <td>${entry.name}</td> <td>${entry.city}</td> <td>${entry.address}</td> <td>${entry.pincode}</td> </tr> </py:for> </tbody> </table> </body> </html>
Теперь снова посетите http: // localhost: 8080 / add и введите данные в форму. Нажав на кнопку «Отправить», вы перейдете в браузер к studentlist.html. Также будет отображено сообщение «новая запись добавлена успешно».
TurboGears — DataGrid
ToscaWidgets содержит элемент управления DataGrid, который обеспечивает быстрый способ представления данных в табличной форме. Объект DataGrid объявлен следующим образом:
from tw2.forms import DataGrid student_grid = DataGrid(fields = [('Name', 'name'),('City', 'city'), ('Address','address'), ('PINCODE', 'pincode')])
Теперь функция showgrid () извлекает все записи в таблице учеников и предоставляет данные в шаблон grid.html. Сначала приведен код для функции showgrid (), а затем код grid.html:
ShowGrid ()
@expose('hello.templates.grid') def showgrid(self): data = DBSession.query(student).all() return dict(page = 'grid', grid = student_grid, data = data)
grid.html
<!DOCTYPE html> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <head> <title>Student Registration Form</title> </head> <body> <div id = "getting_started"> <div>${grid.display(value = data)}</div> </div> </body> </html>
Следующие табличные данные будут отображаться при вводе URL-адреса http: // localhost: 8080 / showlist в браузере —
TurboGears — нумерация страниц
TurboGears предоставляет удобный декоратор paginate () для разделения вывода на страницах. Этот декоратор сочетается с декоратором expose (). Декоратор @Paginate () принимает в качестве аргумента объект словаря результата запроса. Кроме того, количество записей на странице определяется значением атрибута items_per_page. Убедитесь, что вы импортируете функцию paginate из tg.decorators в ваш код.
Перепишите функцию listrec () в root.py следующим образом:
from tg.decorators import paginate class RootController(BaseController): @expose ("hello.templates.studentlist") @paginate("entries", items_per_page = 3) def listrec(self): entries = DBSession.query(student).all() return dict(entries = entries)
Количество элементов на странице должно быть три.
В шаблоне studentlist.html навигация по страницам включается путем добавления tmpl_context.paginators.entries.pager () под директивой py: for. Код для этого шаблона должен быть следующим:
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/"> <head> <link rel = "stylesheet" type = "text/css" media = "screen" href = "${tg.url('/css/style.css')}" /> <title>Welcome to TurboGears</title> </head> <body> <h1>Welcome to TurboGears</h1> <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)"> <div py:if = "flash" py:replace = "Markup(flash)" /> </py:with> <h2>Current Entries</h2> <table border = '1'> <thead> <tr> <th>Name</th> <th>City</th> <th>Address</th> <th>Pincode</th> </tr> </thead> <tbody> <py:for each = "entry in entries"> <tr> <td>${entry.name}</td> <td>${entry.city}</td> <td>${entry.address}</td> <td>${entry.pincode}</td> </tr> </py:for> <div>${tmpl_context.paginators.entries.pager()}</div> </tbody> </table> </body> </html>
Введите http: // localhost: 8080 / listrec в браузере. Первая страница записей в таблице отображаются. Вверху этой таблицы также отображаются ссылки на номера страниц.
Как добавить поддержку пагинации в Datagrid
Также возможно добавить поддержку пагинации в datagrid. В следующем примере разбитая на страницы сетка данных предназначена для отображения кнопки действия. Для активации кнопки действия строится объект datagrid со следующим кодом —
student_grid = DataGrid(fields = [('Name', 'name'),('City', 'city'), ('Address','address'), ('PINCODE', 'pincode'), ('Action', lambda obj:genshi.Markup('<a href = "%s">Edit</a>' % url('/edit', params = dict(name = obj.name)))) ])
Здесь кнопка действия связана с параметром имени каждой строки в сетке данных.
Перепишите функцию showgrid () следующим образом:
@expose('hello.templates.grid') @paginate("data", items_per_page = 3) def showgrid(self): data = DBSession.query(student).all() return dict(page = 'grid', grid = student_grid, data = data)
Браузер показывает разбитую на страницы сетку данных следующим образом:
Нажав кнопку «Изменить» в третьей строке, он будет перенаправлен на следующий URL-адрес http: // localhost: 8080 / edit? Name = Rajesh + Patil
TurboGears — доступ администратора
TurboGears предоставляет расширение tgext.admin, которое работает на tgext.crud и sprox. Этот Sprox представляет собой пакет, используемый для создания веб-виджетов непосредственно из схемы базы данных. Это может быть использовано для автоматического создания простых страниц администрирования и является инструментарием для включения страницы / admin в недавно запущенные приложения.
По умолчанию администратор предоставляет автоматически сгенерированный доступ ко всем моделям, импортированным в модели вашего проекта / __ init__.py.
Как создать TurboGears Admin
Администратор TurboGears по умолчанию создается как объект класса AdminController —
from tgext.admin.controller import AdminController class RootController(BaseController): admin = AdminController(model, DBSession, config_type = TGAdminConfig)
Это создает администратора для всех моделей с конфигурацией администратора TurboGears по умолчанию.
Через менеджера пользователь был создан на этапе установки. Теперь можно получить доступ к администратору TurboGears по адресу http: // localhost: 8080 / admin При первом обращении к этой странице она запросит аутентификацию. Вы можете просто предоставить имя пользователя и пароль пользователя, который команда setup-app создала для нас —
Username: manager Password: managepass
Чтобы войти в проект с быстрым стартом, добавьте следующие функции в класс RootController (controllers / root.py).
from hello.lib.base import BaseController from tg import expose, flash, redirect, request,url, lurl from tg import redirect, validate from hello import model from hello.model import DBSession from tgext.admin.tgadminconfig import BootstrapTGAdminConfig as TGAdminConfig from tgext.admin.controller import AdminController from tg.exceptions import HTTPFound class RootController(BaseController): admin = AdminController(model, DBSession, config_type = TGAdminConfig) @expose('hello.templates.index') def index(self): return dict(page = 'index') @expose('hello.templates.login') def login(self, came_from = lurl('/'), failure = None, login = ''): if failure is not None: if failure == 'user-not-found': flash(_('User not found'), 'error') elif failure == 'invalid-password': flash(_('Invalid Password'), 'error') login_counter = request.environ.get('repoze.who.logins', 0) if failure is None and login_counter > 0: flash(_('Wrong credentials'), 'warning') return dict(page = 'login', login_counter = str(login_counter), came_from = came_from, login = login) @expose() def post_login(self, came_from = lurl('/')): if not request.identity: login_counter = request.environ.get('repoze.who.logins', 0) + 1 redirect('/login', params = dict(came_from = came_from, __logins = login_counter)) userid = request.identity['repoze.who.userid'] flash(('Welcome back, %s!') % userid) return HTTPFound(location = came_from)
Войдите в приложение «quickstarted» после запуска сервера и перейдите по адресу http: // localhost: 8080 / login, а затем введите учетные данные менеджера, как показано выше. Браузер отобразит страницу администратора, как показано ниже —
На странице отображаются все модели, созданные в этом приложении. Вы можете нажать на любую модель, чтобы увидеть список записей в ней —
Кнопка «Создать» в верхней части этой сетки данных позволяет добавить запись. Аналогично, кнопки действий для редактирования и удаления записи также предусмотрены в столбце действий этой таблицы данных. Также отображается окно поиска для условного выбора записей.
TurboGears — авторизация и аутентификация
Приложение TurboGears создается с помощью параметров быстрого запуска и настройки приложения инструментария коробки передач, для которых по умолчанию включена поддержка авторизации и аутентификации. Модели, объявленные в auth.py, устанавливаются и инициализируются в соответствии со значениями, заданными в bootstrap.py.
Следующие модели объявлены в auth.py —
Модель пользователя
Модель User содержит дизайн таблицы tg_user. Эта таблица используется пакетом repose.who. Этот пакет repose.who является мощной и расширяемой библиотекой аутентификации для приложений WSGI. Структура пользовательской модели выглядит следующим образом:
class User(DeclarativeBase): """ __tablename__ = 'tg_user' user_id = Column(Integer, autoincrement = True, primary_key=True) user_name = Column(Unicode(16), unique = True, nullable = False) email_address = Column(Unicode(255), unique = True,nullable=False) display_name = Column(Unicode(255)) _password = Column('password', Unicode(128)) created = Column(DateTime, default = datetime.now)
Эта групповая модель содержит определение таблицы tg_group. Его определение дано в auth.py следующим образом:
class Group(DeclarativeBase): __tablename__ = 'tg_group' group_id = Column(Integer, autoincrement = True,primary_key = True) group_name = Column(Unicode(16),unique = True,nullable = False) display_name = Column(Unicode(255)) created = Column(DateTime, default = datetime.now)
Также настроено другое разрешение модели, которое содержит определение разрешения.
class Permission(DeclarativeBase): __tablename__ = 'tg_permission' permission_id = Column(Integer,autoincrement = True,primary_key = True) permission_name = Column(Unicode(63), unique = True, nullable = False) description = Column(Unicode(255))
Во время настройки моделей в эти таблицы добавляются следующие данные:
u = model.User() u.user_name = 'manager' u.display_name = 'Example manager' u.email_address = '[email protected]' u.password = 'managepass' model.DBSession.add(u) g = model.Group() g.group_name = 'managers' g.display_name = 'Managers Group' g.users.append(u) model.DBSession.add(g) p = model.Permission() p.permission_name = 'manage' p.description = 'This permission gives an administrative right' p.groups.append(g) model.DBSession.add(p) u1 = model.User() u1.user_name = 'editor' u1.display_name = 'Example editor' u1.email_address = '[email protected]' u1.password = 'editpass' model.DBSession.add(u1)
Модель предиката
Модуль предикатов в пакете tg содержит определения для проверки предикатов. Предикат — это условие, которое должно быть выполнено, чтобы пользователь мог получить доступ к запрошенному источнику. Такой предикат или условие может состоять из большего числа предикатов — они называются составными предикатами. Контроллеры действий или контроллеры могут иметь только один предикат, будь то отдельный или составной.
Если пользователь не вошел в систему или не имеет надлежащих разрешений, эта программа проверки предикатов выбрасывает 401 (HTTP Unauthorized), который перехватывается промежуточным программным обеспечением repoze.who, чтобы отобразить страницу входа, позволяющую пользователю войти в систему, и перенаправить пользователь вернется на соответствующую страницу, когда они будут сделаны.
Различные условия или предикаты, определенные в модуле tg.predicates:
Sr.No. | Модуль и описание tg.predicates |
---|---|
1 |
Все Проверьте, выполнены ли все указанные предикаты |
2 |
любой Проверьте, соответствует ли хотя бы один из указанных предикатов |
3 |
is_user Убедитесь, что имя пользователя, прошедшего аутентификацию, является указанным |
4 |
в группе Убедитесь, что пользователь принадлежит к определенной группе. |
5 |
in_all_groups Убедитесь, что пользователь принадлежит ко всем указанным группам. |
6 |
in_any_group Убедитесь, что пользователь принадлежит хотя бы к одной из указанных групп. |
7 |
is_anonymous Убедитесь, что текущий пользователь является анонимным. |
8 |
has_permission Убедитесь, что текущий пользователь имеет указанное разрешение. |
9 |
has_all_permissions Убедитесь, что текущему пользователю предоставлены все указанные разрешения. |
10 |
has_any_permission Убедитесь, что у пользователя есть хотя бы одно из указанных разрешений. |
Все
Проверьте, выполнены ли все указанные предикаты
любой
Проверьте, соответствует ли хотя бы один из указанных предикатов
is_user
Убедитесь, что имя пользователя, прошедшего аутентификацию, является указанным
в группе
Убедитесь, что пользователь принадлежит к определенной группе.
in_all_groups
Убедитесь, что пользователь принадлежит ко всем указанным группам.
in_any_group
Убедитесь, что пользователь принадлежит хотя бы к одной из указанных групп.
is_anonymous
Убедитесь, что текущий пользователь является анонимным.
has_permission
Убедитесь, что текущий пользователь имеет указанное разрешение.
has_all_permissions
Убедитесь, что текущему пользователю предоставлены все указанные разрешения.
has_any_permission
Убедитесь, что у пользователя есть хотя бы одно из указанных разрешений.
Например, если у вас есть предикат, то есть пользователь с разрешенным доступом, принадлежащий к группе клиентов , вы можете использовать следующую встроенную проверку предикатов:
from tg.predicates import in_group p in_group(‘customers’)
Следующая проверка предикатов предоставит доступ пользователю root или кому-либо с правами на управление:
from tg.predicates import Any, is_user, has_permission p = Any(is_user('root'), has_permission('manage'), sg = 'Only administrators can remove blog posts')
TurboGears — Использование MongoDB
TurboGears также поддерживает базы данных документов MongoDB. Он использует Ming, API Object Document Mapper. Использование Ming очень похоже на SQLAlchemy. Язык запросов Ming позволяет портировать проект TurboGears на основе SQLAlchemy в Ming.
Что такое PyMongo
PyMongo — это дистрибутив Python, содержащий инструменты для работы с MongoDB. Ming расширяет возможности PyMongo —
- Декларативные модели
- Проверка схемы и преобразование
- Схема Эволюция
- Внедрение Pure InMemory MongoDB
- Единица работы
- Карта личности
- Отношения один-ко-многим, многие-к-одному и многие-ко-многим
Прежде всего, вам необходимо скачать и установить MongoDB. Последний дистрибутив MongoDB можно скачать по адресу https://www.mongodb.org/downloads.
В Windows запустите сервер MongoDB, указав опцию -dbpath —
C:\mongodb\bin>Mongod --dbpath d:\mongo
Папка D: \ mongo предназначена для хранения базы данных MongoDB. Сервер начинает прослушивание по адресу http: // localhost: 27017. Теперь для запуска оболочки MongoDB используйте следующую команду —
C:\mongodb\bin>Mongo
Наша среда MongoDB теперь готова.
Теперь создайте проект TurboGears с опцией -ming —
gearbox quickstart --ming Hello
Этот проект с быстрым запуском обеспечит уровень аутентификации и авторизации, подобный тому, который предоставляется для версии SQLAlchemy. Это приложение теперь попытается подключиться к серверу через порт 27017 на локальном компьютере. Файл development.ini в папке проекта содержит следующие параметры:
ming.url = mongodb://localhost:27017/ ming.db = hello
Настройте проект с помощью следующей команды —
Python setup.py develop
Папка проекта содержит подпапку моделей, в которой находятся следующие файлы:
-
__init__.py — здесь настраивается доступ к базе данных . Ваши коллекции должны быть импортированы в этот модуль . Например, мы добавим студенческую коллекцию в этот пакет.
-
session.py — Этот файл определяет сеанс подключения к вашей базе данных . Вам нужно будет импортировать это каждый раз, когда вам нужно объявить MappedClass, чтобы указать сеанс для выполнения запросов .
-
auth.py — этот файл будет создан, если вы включили аутентификацию и авторизацию в быстром запуске . Он определяет три коллекции repoze .who, которые также зависят от: User, Group и Permission.
__init__.py — здесь настраивается доступ к базе данных . Ваши коллекции должны быть импортированы в этот модуль . Например, мы добавим студенческую коллекцию в этот пакет.
session.py — Этот файл определяет сеанс подключения к вашей базе данных . Вам нужно будет импортировать это каждый раз, когда вам нужно объявить MappedClass, чтобы указать сеанс для выполнения запросов .
auth.py — этот файл будет создан, если вы включили аутентификацию и авторизацию в быстром запуске . Он определяет три коллекции repoze .who, которые также зависят от: User, Group и Permission.
Определение вашей коллекции
По умолчанию TurboGears настраивает Ming в декларативном режиме. Это похоже на декларативную поддержку SQLAlchemy, и каждая модель должна наследоваться от класса MappedClass.
MappedClass требует, чтобы внутри был доступен подкласс __mongometa__, который дополнительно предоставляет подробную информацию относительно имени коллекции, в которой хранятся документы, и сеанса, используемого для хранения документов.
MappedClass также содержит определение полей в документе. Модуль Odm от Ming имеет определения различных типов свойств полей —
- FieldProperty
- ForeignIdProperty
- RelationProperty
Модуль ming.schema определяет следующие типы данных —
- ming.schema.Anything
- ming.schema.Array
- ming.schema.Binary
- ming.schema.Bool
- ming.schema.Float
- ming.schema.Int
- ming.schema.ObjectId
- ming.schema.Scalar
- ming.schema.String
Чтобы добавить коллекцию учеников в эту модель, сохраните следующий код как student.py в папке hello / models.
Привет \ модели \ student.py
from ming import schema from ming.odm import MappedClass from ming.odm import FieldProperty, ForeignIdProperty from hello.model import DBSession Class student(MappedClass): class __mongometa__: session = DBSession name = 'student' _id = FieldProperty(schema.ObjectId) name = FieldProperty(schema.String(required = True)) city = FieldProperty(schema.String(if_missing = '')) address = FieldProperty(schema.String(if_missing = '')) pincode = FieldProperty(schema.String(if_missing = ''))
Наконец, включите эту модель в hello \ models \ __ init__.py
# Import your model modules here. from hello.model.auth import User, Group, Permission from hello.model.student import student
Чтобы настроить эти модели, выполните следующую команду коробки передач —
Gearbox setup-app
Запустите сервер с помощью следующей команды коробки передач —
Gearbox serve –reload –debug
Откройте домашнюю страницу этого приложения (http: // localhost: 8080 /) и войдите с учетными данными менеджера. Страница администратора этого приложения покажет список настроенных моделей. (войдите как менеджер, пароль паролей)
Создание коллекций также можно проверить в веб-интерфейсе MongoDB и в оболочке MongoDB.
ODMSession используется для выполнения нескольких операций с базой данных с использованием следующих функций:
- model.query.find ()
- model.query.find_and_modify ()
- model.remove ()
- model.update ()
- model.flush ()
Разработка формы ToscoWidget
Теперь мы разработаем форму ToscoWidget для ввода данных об учащемся и добавим их в таблицу, лежащую в основе модели учащегося.
Ниже приведен код для создания studentform.py —
Привет \ Контроллеры \ studentform.py
import tw2.core as twc import tw2.forms as twf class StudentForm(twf.Form): class child(twf.TableLayout): name = twf.TextField(size = 20) city = twf.TextField() address = twf.TextArea("",rows = 5, cols = 30) pincode = twf.NumberField() action = '/save_record' submit = twf.SubmitButton(value = 'Submit')
В URL-адресе приложения / Rootcontroller ‘/ add’, который вызывает функцию add (), которая откроет вышеуказанную форму в браузере. Затем кнопка «Отправить» вызывает функцию save_record (). Он извлекает данные формы и сохраняет их в таблице учеников и перенаправляет приложение на URL-адрес «/ listrec», который предоставляет шаблон списка учеников.
Root.py для этого действия выглядит следующим образом —
Привет / Контроллеры / root.py
from hello.lib.base import BaseController from tg import expose, flash, redirect, request,url, lurl from tg import redirect, validate from hello import model from hello.model import DBSession from hello.model.student import student from hello.controllers.studentform import StudentForm class RootController(BaseController): @expose() def index(self): return "<h1>Hello World</h1>" @expose ("hello.templates.studentlist") def listrec(self): entries = student.query.find() return dict(entries = entries) @expose('hello.templates.studentform') def add(self, *args, **kw): return dict(page = 'studentform', form = StudentForm) @expose() def save_record(self, **kw): newstudent = student(name = kw['name'],city = kw['city'], address = kw['address'], pincode = kw['pincode']) DBSession.flush() flash(message = "new entry added successfully") redirect("/listrec")
Следующие шаблоны создаются в папке шаблонов —
Привет \ Шаблоны \ studentform.html
<!DOCTYPE html> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <head> <title>Student Registration Form</title> </head> <body> <div id = "getting_started"> ${form.display(value = dict(title = 'Enter data'))} </div> </body> </html>
Привет \ Шаблоны \ studentlist.html
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/"> <head> <link rel = "stylesheet" type = "text/css" media = "screen" href = ${tg.url('/css/style.css')}" /> <title>Welcome to TurboGears</title> </head> <body> <h1>Welcome to TurboGears</h1> <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)"> <div py:if = "flash" py:replace = "Markup(flash)" /> </py:with> <h2>Current Entries</h2> <table border = '1'> <thead> <tr> <th>Name</th> <th>City</th> <th>Address</th> <th>Pincode</th> </tr> </thead> <tbody> <py:for each = "entry in entries"> <tr> <td>${entry.name}</td> <td>${entry.city}</td> <td>${entry.address}</td> <td>${entry.pincode}</td> </tr> </py:for> </tbody> </table> </body> </html>
Перезагрузите сервер и введите в браузере http: // localhost: 8080 / add —
Каждый раз, когда данные добавляются и нажимается кнопка отправки, будет отображаться список текущих записей.
TurboGears — Строительные леса
Инструментарий Gearbox содержит команду scaffold, которая очень полезна для быстрого создания новых компонентов приложения TurboGears. Приложение, созданное командой quickstart для gearbox, имеет шаблон каркаса в папке модели (model.py.template), папку шаблонов (template.html.template) и папку контроллеров (controller.py.template). Эти файлы .template используются в качестве основы для создания новых скаффолдов для приложения.
Например, чтобы создать новую модель с именем mymodel, просто выполните следующую команду —
gearbox scaffold model mymodel
Эта команда сгенерирует модель / mymodel.py с определенным в ней классом newmodel.
# -*- coding: utf-8 -*- """Mymodel model module.""" from sqlalchemy import * from sqlalchemy import Table, ForeignKey, Column from sqlalchemy.types import Integer, Unicode, DateTime, LargeBinary from sqlalchemy.orm import relationship, backref from hello.model import DeclarativeBase, metadata, DBSession class Mymodel(DeclarativeBase): __tablename__ = 'mymodels' uid = Column(Integer, primary_key = True) data = Column(Unicode(255), nullable = False) user_id = Column(Integer, ForeignKey('tg_user.user_id'), index = True) user = relationship('User', uselist = False, backref = backref('mymodels',cascade = 'all, delete-orphan')) __all__ = ['Mymodel']
Теперь пользователи могут вносить изменения в структуру таблицы в соответствии со своими требованиями, а затем импортировать ее в модель / __ init__.py, чтобы сделать модель доступной внутри приложения.
Чтобы создать модель, класс контроллера для ее обработки и индексную страницу, все эти три компонента могут быть созданы одновременно с помощью следующей команды.
gearbox scaffold model controller template mymodel
Эта команда приведет к controllers \ mymodel.py, в котором класс MymodelController должным образом определен.
# -*- coding: utf-8 -*- """Mymodel controller module""" from tg import expose, redirect, validate, flash, url # from tg.i18n import ugettext as _ # from tg import predicates from hello.lib.base import BaseController # from hello.model import DBSession class MymodelController(BaseController): # Uncomment this line if your controller requires an authenticated user # allow_only = predicates.not_anonymous() @expose('hello.templates.mymodel') def index(self, **kw): return dict(page = 'mymodel-index')
Чтобы начать использовать этот контроллер, смонтируйте его внутри RootController вашего приложения, просто чтобы определить экземпляр MymodelController. Добавьте эти строки в controllers \ root.py —
From hello.controller.mymodel import MymodelController class RootController(BaseController): mymodel = MymodelController()
Шаблон scaffold templates \ mymodel.html также будет создан в папке шаблонов. Он будет выступать в качестве индексной страницы для URL / mymodel.
Сгенерированный файл mymodel.html в папке шаблонов будет выглядеть следующим образом:
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" xmlns:xi = "http://www.w3.org/2001/XInclude"> <xi:include href = "master.html" /> <head> <title>Mymodel</title> </head> <body> <div class = "row"> <div class = "col-md-12"> <h2>Mymodel</h2> <p>Template page for Mymodel</p> </div> </div> </body> </html>
TurboGears — Крючки
В TurboGears есть три способа подключения поведения внутри существующих приложений.
-
Крюк — это механизм, с помощью которого можно определить событие и уведомить зарегистрированных слушателей о том, когда и когда происходят события.
-
Контроллер Wrapper — Он расположен между TurboGears и Controller, так что можно расширить контроллер как декоратор. Таким образом, его можно подключить к любому стороннему контроллеру приложения.
-
Application Wrapper — похож на любое промежуточное ПО WSGI, но работает только в контексте TurboGears.
Крюк — это механизм, с помощью которого можно определить событие и уведомить зарегистрированных слушателей о том, когда и когда происходят события.
Контроллер Wrapper — Он расположен между TurboGears и Controller, так что можно расширить контроллер как декоратор. Таким образом, его можно подключить к любому стороннему контроллеру приложения.
Application Wrapper — похож на любое промежуточное ПО WSGI, но работает только в контексте TurboGears.
Здесь, в этой главе, мы обсудим, как использовать хуки внутри существующего приложения.
Крючки
Хуки — это события, зарегистрированные в файле конфигурации приложения app_cfg.py . Любой контроллер затем подключается к этим событиям декораторами событий.
Следующие хуки определены в TurboGears —
Sr.No. | Крючки и описание |
---|---|
1 |
Запускать() только для всего приложения, вызывается при запуске приложения. |
2 |
неисправность() только приложение, вызывается при выходе из приложения. |
3 |
configure_new_app новое приложение создано конфигуратором приложения. |
4 |
before_config (приложение) только для всего приложения, вызывается сразу после создания приложения, но до настройки параметров и промежуточного программного обеспечения |
5 |
after_config (приложение) только для всего приложения, вызывается после завершения настройки. |
6 |
before_validate Вызывается перед выполнением проверки |
7 |
before_call Вызывается после проверки, перед вызовом фактического метода контроллера. |
8 |
before_render Вызывается перед рендерингом шаблона контроллера. Выходное значение — возвращаемое значение контроллера. |
9 |
after_render Вызывается после окончания рендеринга шаблона контроллера. |
Запускать()
только для всего приложения, вызывается при запуске приложения.
неисправность()
только приложение, вызывается при выходе из приложения.
configure_new_app
новое приложение создано конфигуратором приложения.
before_config (приложение)
только для всего приложения, вызывается сразу после создания приложения, но до настройки параметров и промежуточного программного обеспечения
after_config (приложение)
только для всего приложения, вызывается после завершения настройки.
before_validate
Вызывается перед выполнением проверки
before_call
Вызывается после проверки, перед вызовом фактического метода контроллера.
before_render
Вызывается перед рендерингом шаблона контроллера. Выходное значение — возвращаемое значение контроллера.
after_render
Вызывается после окончания рендеринга шаблона контроллера.
Зарегистрировать крюк
Чтобы зарегистрировать хук, создайте функции в app_cfg.py, а затем зарегистрируйте их, используя следующий код —
tg.hooks.register(hookane, function, controller)
В следующем коде хуки on_startup, on_shutdown и before_render зарегистрированы в app_cfg.py.
def on_startup(): print 'hello, startup world' def on_shutdown(): print 'hello, shutdown world' def before_render(remainder, params, output): print 'system wide before render' # ... (base_config init code) tg.hooks.register('startup', on_startup) tg.hooks.register('shutdown', on_shutdown) tg.hooks.register('before_render', before_render)
Хук before_render зарегистрирован с помощью функции контроллера в Rootcontroller. Добавьте следующий код в controllers \ root.py.
from tg.decorators import before_render class RootController(BaseController): @expose('hello.templates.index') @before_render(before_render_cb) def index(self, *args, **kw): return dict(page = 'index')
Когда приложение обслуживается, в консоли отображается сообщение о запуске.
hello, startup world Starting Standard HTTP server on http://127.0.0.1:8080
Когда в браузере вводится URL ‘/’, на консоли отображается сообщение, соответствующее хуку before_render.
system wide before render Going to render {'page': 'index'}
TurboGears — Написание расширений
Расширения TurboGears идентифицируются пакетом tgext. * . Инструментарий Gearbox предоставляет команду tgext для создания примера расширения. Например —
gearbox tgext -n myextension
Другие необязательные параметры для этой команды:
-
—author — имя автора пакета.
-
—email — адрес электронной почты автора пакета.
-
—licence — лицензия, используемая для пакета. По умолчанию это MIT.
-
—description — Описание пакета.
-
—keywords — Пакет ключевых слов (по умолчанию: turbogears2.extension).
—author — имя автора пакета.
—email — адрес электронной почты автора пакета.
—licence — лицензия, используемая для пакета. По умолчанию это MIT.
—description — Описание пакета.
—keywords — Пакет ключевых слов (по умолчанию: turbogears2.extension).
Это создаст каталог tgext.myextension, который имеет простой пример расширения внутри.
Запустите setup.py внутри каталога —
Python setup.py install
Файл _init_.py внутри папки tgext / myextension содержит —
-
Функция Plugme — это точка входа в расширение.
-
Класс SetupExtension — здесь происходит инициализация расширения.
-
Функция On_startup — внутри класса есть хук, зарегистрированный в функции __call__ внутри класса.
Функция Plugme — это точка входа в расширение.
Класс SetupExtension — здесь происходит инициализация расширения.
Функция On_startup — внутри класса есть хук, зарегистрированный в функции __call__ внутри класса.
Краткая версия tgext \ myextension \ __ init__.py .
from tg import config from tg import hooks from tg.configuration import milestones import logging log = logging.getLogger('tgext.myextension') def plugme(configurator, options = None): if options is None: options = {} log.info('Setting up tgext.myextension extension...') milestones.config_ready.register(SetupExtension(configurator)) return dict(appid='tgext.myextension') class SetupExtension(object): def __init__(self, configurator): self.configurator = configurator def __call__(self): log.info('>>> Public files path is %s' % config['paths']['static_files']) hooks.register('startup', self.on_startup) def echo_wrapper_factory(handler, config): def echo_wrapper(controller, environ, context): log.info('Serving: %s' % context.request.path) return handler(controller, environ, context) return echo_wrapper self.configurator.register_wrapper(echo_wrapper_factory) def on_startup(self): log.info('+ Application Running!')
После того, как расширение установлено, включите его, сделав следующие дополнения в файле конфигурации приложения app_cfg.py .
from tgext.myextension import plugme plugme(base_config)
Если мы запускаем сервер с помощью команды сервера коробки передач, уведомление о недавно зарегистрированном расширении можно просмотреть на консоли следующим образом:
14:29:13,250 INFO [tgext.myextension] Setting up tgext.myextension extension... 14:29:13,453 INFO [tgext.myextension] >>> Public files path is c:\tghello\hello\hello\public 14:29:13,453 INFO [tgext.myextension] + Application Running! Starting Standard HTTP server on http://127.0.0.1:8080
TurboGears — Сменные приложения
Если вашему расширению необходимо предоставить модели и контроллеры, вы, вероятно, захотите взглянуть на Pluggable Applications , которые предназначены для создания повторно используемых приложений Turbogears, которые можно подключать к другим приложениям для расширения их функций.
Используйте следующую команду gearbox для создания подключаемого приложения:
gearbox quickstart-pluggable plugtest
Эти подключаемые приложения могут определять свои собственные —
-
Контроллеры — которые будут автоматически монтироваться при удалении приложения.
-
Модели — которые будут доступны внутри и снаружи подключенного приложения.
-
Помощники — которые могут автоматически отображаться в объекте «H» в шаблоне приложения.
-
Bootstrap — запускается при вызове setup-app.
-
Статика — которая будет доступна по собственному личному пути.
Контроллеры — которые будут автоматически монтироваться при удалении приложения.
Модели — которые будут доступны внутри и снаружи подключенного приложения.
Помощники — которые могут автоматически отображаться в объекте «H» в шаблоне приложения.
Bootstrap — запускается при вызове setup-app.
Статика — которая будет доступна по собственному личному пути.
Установите это приложение plugtest и смонтируйте его, внеся следующие изменения в app_cfg.py .
from tgext.pluggable import plug plug(base_config, plugtest)
TurboGears — RESTful приложения
REST означает RE презентационный Государственный перевод. REST — это архитектура, основанная на веб-стандартах и использующая протокол HTTP для передачи данных. Он вращается вокруг ресурса, где каждый компонент является ресурсом, а доступ к ресурсу осуществляется с помощью общего интерфейса с использованием стандартных методов HTTP. REST был впервые представлен Роем Филдингом в 2000 году .
Что такое RestController
RestController в TurboGears предоставляет механизм доступа к методу запроса, а не только к URL. Стандартное словосочетание HTTP включает в себя: GET, POST, PUT и DELETE. RestController поддерживает их, а также добавляет несколько ярлыков для рассылки URL-адресов, что делает отображение данных в виде форм и списков более удобным для пользователя.
Чтобы объяснить, как RESTful работает с TurboGears, мы собираемся определить простой веб-сервис, который предоставляет список студентов.
Код для модели студента приведен ниже —
модель \ student.py
# -* - coding: utf-8 -*- from sqlalchemy import * from sqlalchemy.orm import mapper, relation, relation, backref from sqlalchemy import Table, ForeignKey, Column from sqlalchemy.types import Integer, Unicode, DateTime from hello.model import DeclarativeBase, metadata, DBSession from datetime import datetime class student(DeclarativeBase): __tablename__ = 'student' uid = Column(Integer, primary_key = True) name = Column(Unicode(20), nullable = False, default = '') city = Column(Unicode(20), nullable = False, default = '') address = Column(Unicode(100), nullable = False, default = '') pincode = Column(Unicode(10), nullable = False, default = '')
Теперь создайте контроллер на основе RestController и предоставьте функцию просмотра для вывода списка учеников в формате json.
Контроллеры \ student.py
from tg import RestController from tg import expose from hello import model from hello.model import DBSession from hello.model.student import student from tg.decorators import with_trailing_slash class StudentController(RestController): @expose('json') def get_all(self): students = DBSession.query(student).all() return dict(students=students)
Смонтируйте этот StudentController в RootController приложения, добавив следующие строки в root.py —
from hello.controllers.student import StudentController class RootController(BaseController): students = StudentController()
Перейдя по адресу http: // localhost: 8080 / student, он предоставит список наших студентов в формате json.
Мы используем метод post, чтобы определить, как мы сохраняем нашего ученика в базе данных. Этот метод вызывается всякий раз, когда к URL-адресу http: // localhost: 8080 / student выполняется запрос POST —
@expose('json') def post(self, name, city, address, pincode): newstudent = student(name = name, city = city, address = address, pincode = pincode) DBSession.add(newstudent) DBSession.flush() return dict(student = newstudent)
Используя метод get_one () , мы можем отобразить один элемент из базы данных пользователю —
@expose('json') def get_one(self, movie_id): newstudent = DBSession.query(student).get(uid) return dict(movie = movie)
PUT — метод, используемый для обновления существующей записи с использованием REST —
@expose('json') def put(self, name = name, city = city, address = address, pincode = pincode, **kw): newstudent = DBSession.query(student).get(name) newstudent.name = name newstudent.city = city newstudent.address = address newstudent.pincode = pincode return dict(student = newstudent)
Рабочая лошадка удаления прикреплена к методу post_delete. Здесь мы фактически удаляем запись из базы данных, а затем перенаправляем обратно на страницу листинга —
@expose('json') def post_delete(self, uid, **kw): newstudent = DBSession.query(student).get(uid) DBSession.delete(newstudent) return dict(movie = newstudent.uid)
TurboGears — Развертывание
Для перехода от среды разработки к полноценной производственной среде необходимо развернуть приложение на реальном веб-сервере. В зависимости от того, что у вас есть, для развертывания веб-приложения TurboGears доступны разные варианты.
Apache с mod_wsgi
Mod_wsgi — это модуль Apache, разработанный Грэмом Дамплтоном. Он позволяет обслуживать программы WSGI с помощью веб-сервера Apache.
Во-первых, установите Apache 2.X для вашей платформы, если это еще не сделано. После установки Apache установите mod_wsgi. Создайте и активируйте виртуальную среду Python на сервере и установите на нем TurboGears.
Установите ваше приложение в директории приложения, затем создайте скрипт с именем app.wsgi .
Настройте установку Apache следующим образом:
<VirtualHost *:80> ServerName www.site1.com WSGIProcessGroup www.site1.com WSGIDaemonProcess www.site1.com user = <username> group = www-data threads = 4 python-path = <pythonpath> WSGIScriptAlias myapp/app.wsgi #Serve static files directly without TurboGears Alias /images Alias /css Alias /js CustomLog ErrorLog </VirtualHost>
Перезапустите Apache
Введите http://www.site1.com/ в браузере, чтобы получить доступ к приложению.
TurboGears под цирк и шоссет
Цирк — менеджер процессов и сокетов. Он может быть использован для мониторинга и контроля процессов и сокетов. В сочетании с сервером Chaussette WSGI он может стать мощным инструментом для развертывания приложения и управления любым связанным процессом, в котором нуждаются ваши приложения.
TurboGears — GoogleAppEngine
Установите Google AppEngine SDK для Python по следующему URL-адресу — https: //cloud.google.coms
Установите Google AppEngine в своей системе. Затем откройте консоль разработчика Google и войдите в свою учетную запись Google — https://console.developers.google.com/start.
Создайте новый проект под названием mytgapp —
Используя Google AppEngine Launcher, создайте новое приложение с именем mytgapp.
Следующие файлы будут созданы в указанном каталоге —
- app.yaml
- favicon.ico
- index.yaml
- main.py
По умолчанию созданное приложение использует платформу Webapp2. Чтобы удалить эту зависимость, отредактируйте файл app.yaml и удалите следующую часть:
libraries: - name: webapp2 version: "2.5.2"
Создайте временную виртуальную среду в каталоге с именем mytgapp и установите TurboGears. Создайте в нем приложение TurboGears. Теперь мы можем продолжить редактирование файла main.py, который запускается AppEngine, чтобы запустить наше приложение и фактически написать там приложение TurboGears.
Добавьте следующее содержимое в main.py —
import os import site site.addsitedir(os.path.join(os.path.dirname(__file__), 'packages')) from tg import expose, TGController, AppConfig class RootController(TGController): @expose() def index(self): return "<h1>Hello World</h1>" config = AppConfig(minimal = True, root_controller = RootController()) app = config.make_wsgi_app()
Теперь запустите приложение из AppEngine Launcher и нажмите кнопку обзора, чтобы убедиться, что приложение работает на локальном хосте.
Мы уже создали проект с именем mytgapp в консоли разработчика. Теперь нажмите кнопку развертывания в Launcher. После завершения процесса развертывания посетите веб-сайт http://mytgapp.appspot.com/, чтобы просмотреть наше приложение в Интернете.