Turbogears - Краткое руководство

Что такое веб-платформа?

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

Что такое TurboGears?

TurboGears - это среда веб-приложений, написанная на Python. Первоначально созданная Кевином Дангуром в 2005 году, последняя версия TurboGears (версия 2.3.7) управляется группой разработчиков во главе с Марком Раммом и Флораном Эйдом.

TurboGears следует парадигме модель-представление-контроллер, как и большинство современных веб-фреймворков, таких как Rails, Django, Struts и т. Д.

Контроллер представления модели

MVC - это шаблон проектирования программного обеспечения для разработки веб-приложений. Шаблон Model View Controller состоит из трех частей:

  • Model - Самый нижний уровень шаблона отвечает за поддержание данных.

  • View - Он отвечает за отображение всех или части данных для пользователя.

  • Controller - Программный код, который контролирует взаимодействие между моделью и представлением.

MVC популярен, поскольку он изолирует логику приложения от уровня пользовательского интерфейса и поддерживает разделение задач. Здесь Контроллер получает все запросы для приложения, а затем работает с моделью, чтобы подготовить любые данные, необходимые для представления. Затем представление использует данные, подготовленные контроллером, для генерации окончательного презентабельного ответа. Абстракция MVC может быть графически представлена ​​следующим образом:

Модель

Модель отвечает за управление данными приложения. Он отвечает на запрос из представления, а также отвечает на инструкции контроллера по обновлению.

Вид

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

Контроллер

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

TurboGears построен на основе ряда библиотек и инструментов. Эти инструменты менялись между различными версиями TurboGears. Компоненты текущей версии (2.3.7) перечислены ниже.

SQLAlchemy

Это набор SQL с открытым исходным кодом, который обеспечивает сопоставление объектных отношений (ORM) для кода Python.

Генши

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

ToscaWidgets

Это библиотека виджетов для создания HTML-форм с элементами управления на стороне сервера. Tosca также действует как промежуточное ПО для связи с виджетами и инструментами JavaScript.

Коробка передач

Он предоставляет набор команд для управления проектами и серверными приложениями TurboGears. Приложения TurboGears можно развернуть на любом веб-сервере, совместимом с WSGI.

Интерфейс шлюза веб-сервера (WSGI) был принят в качестве стандарта для разработки веб-приложений Python. WSGI - это спецификация универсального интерфейса между веб-сервером и веб-приложениями. Пакет wsgiref - это эталонная реализация WSGI. Он используется для добавления поддержки WSGI в веб-платформу Web TurboGears. Модуль simple_server в этом пакете реализует простой HTTP-сервер, обслуживающий приложения WSGI. Мы будем использовать его для тестирования приложений, разработанных в этом руководстве.

Предпосылка

Python 2.6 или выше. Более ранние версии TurboGears несовместимы с Python 3.X. Последняя версия утверждает, что хорошо работает с Python 3.X. Однако официальная документация TurboGears по-прежнему основана на среде Python 2.7.

Следующая команда installs virtualenv -

pip install virtualenv

Эта команда требует administratorпривилегии. Добавитьsudo before 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

Теперь мы готовы install TurboGearsв этой среде. Минимальная установка TurboGears выполняется следующей командой -

pip install TurboGears2

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

Чтобы установить TurboGears вместе со средствами разработки, используйте следующую команду -

pip install tg.devtools

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 localhost.

Ниже приведен полный код нашего первого приложения 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.devtoolsTurboGears содержит коробку передач. Это набор команд, которые полезны для управления более сложными проектами TG. Полностековые проекты можно быстро создать с помощью следующей команды Gearbox -

gearbox quickstart HelloWorld

Это создаст проект под названием HelloWorld.

Проект TurboGears содержит следующие каталоги -

  • Config - Откуда зависит установка и настройка проекта

  • Controllers - Все контроллеры проекта, логика веб-приложения

  • i018n - Файлы перевода для поддерживаемых языков

  • Lib - Служебные функции и классы Python

  • Model - Модели базы данных

  • Public Static Files - CSS, JavaScript и изображения

  • Templates - Шаблоны, предоставляемые нашими контроллерами.

  • Tests - Выполнен набор тестов.

  • Websetup - Функции для выполнения при настройке приложения.

Как установить проект

Теперь этот проект необходимо установить. Аsetup.pyуже присутствует в базовом каталоге проекта. При выполнении этого скрипта устанавливаются зависимости проекта.

Python setup.py develop

По умолчанию во время настройки проекта устанавливаются следующие зависимости:

  • Beaker
  • Genshi
  • zope.sqlalchemy
  • sqlalchemy
  • alembic
  • repoze.who
  • tw2.forms
  • tgext.admin ≥ 0.6.1
  • WebHelpers2
  • babel

После установки начните обслуживать проект на сервере разработки, выполнив следующую команду в оболочке -

Gearbox serve –reload –debug

Следуйте указанной выше команде, чтобы показать готовый пример проекта. открытоhttp://localhost:8080в браузере. Этот готовый пример приложения дает краткое введение в сам фреймворк TurboGears.

В этом проекте Hello контроллер по умолчанию создается в каталоге контроллеров как Hello/hello/controllers.root.py. Разрешите намmodify 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() декоратор прикрепляет /sayHelloURL к нему. Эта функция предназначена для приема имени в качестве параметра URL-адреса.

После запуска сервера через команду 'gearbox serve', http://localhost:8080. Сообщение Hello World будет отображаться в браузере, даже если будут введены следующие URL-адреса:

http://localhost:8080/

http://localhost:8080/index

Все эти 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 folder приложения.

Его код следующий -

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__ отправляет в метод контроллера, на который направлен запрос.

Событие, хотя содержимое HTML может быть возвращено в браузер, для более продвинутого вывода всегда предпочтительнее использовать механизм шаблонов. В полномасштабном проекте, запущенном с помощью gearbox, Genshi включен в качестве средства визуализации шаблонов по умолчанию. Однако в минимальном приложении Genshi (или любой другой шаблонизатор, например jinja) должен быть установлен и включен. Механизм шаблонов Genshi позволяет писать шаблоны в чистом xhtml и проверять их, чтобы обнаруживать проблемы во время компиляции и предотвращать обслуживание сломанных страниц.

Шаблоны обозначены пунктирной нотацией. В нашем проекте Hello предоставляется каталог шаблонов для хранения шаблонов веб-страниц. Следовательноsample.html будет называться hello.templates.sample(расширение не упоминается). TurboGears отображает этот шаблон через декоратор экспонирования, чтобы связать с ним метод контроллера с помощьюtg.render_template() функция.

Открытая функция контроллера возвращает объект словаря Python. Этот объект словаря, в свою очередь, передается в связанный шаблон. Заполнители в шаблоне заполняются словарными значениями.

Для начала давайте отобразим веб-страницу с помощью простого html-скрипта. Открытый контроллер возвращаетnull dictionary object поскольку мы не намерены отправлять какие-либо данные для анализа внутри 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-форма используется для отправки данных формы.

Протокол Http - это основа передачи данных во всемирной паутине. В этом протоколе определены различные методы получения данных с указанного URL. В следующей таблице приведены различные методы http:

Sr.No. Методы и описание HTTP
1

GET

Отправляет данные на сервер в незашифрованном виде. Самый распространенный метод.

2

HEAD

То же, что GET, но без тела ответа

3

POST

Используется для отправки данных HTML-формы на сервер. Данные, полученные методом POST, сервером не кэшируются.

4

PUT

Заменяет все текущие представления целевого ресурса загруженным контентом.

5

DELETE

Удаляет все текущие представления целевого ресурса, заданные 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>

Данные, введенные в эту форму, должны быть отправлены в ‘/login’ URL. Теперь создайте функцию контроллера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 template engine чтобы сгенерировать следующий вывод -

Метод 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 отобразит следующий вывод -

Genshi - это язык шаблонов на основе XML. Это похоже наKid, который раньше был механизмом шаблонов для более ранних версий TurboGears. Генши и Кид вдохновлены другими известными языками шаблонов, такими как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 определен ряд директив. В следующем списке перечислены директивы Генши -

  • py:if
  • py:choose
  • py:for
  • py:def
  • py:match
  • py:with
  • py:replace
  • py:content
  • py:attrs
  • py:strip

Условные разделы

Genshi предоставляет две директивы для условного рендеринга контента - py: if и py: choose.

ру: если

Содержимое элемента этой директивы будет отображаться, только если выражение в if clauseоценивается как истина. Предполагая, что данные в контексте шаблона{‘foo’:True, ‘bar’:’Hello’}, следующая директива -

<div>
   <b py:if = "foo">${bar}</b>
</div>

приведет к

Hello

Однако этот вывод не будет отображаться, если ‘foo’ is set to False.

Эта директива также может использоваться как элемент. В этом случае<py:if> должны быть закрыты соответствующими </py:if>

<div>
   <py:if test = "foo">
      <b>${bar}</b>
   </py:if>
</div>

ру: выбрать

Возможна расширенная условная обработка с использованием py:choose в комбинации с py:when и py:otherwiseдирективы. Эта функция похожа наswitch – case построить в C/C++.

Выражение в py:choose директива проверяется с разными значениями, идентифицированными с py:whenальтернативы и соответствующее содержимое будут отображены. Альтернатива по умолчанию может быть предоставлена ​​в видеpy:otherwise директива.

<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-форма отправляет данные в / отмечает URL. Вmarks() функция перенаправляет метки и результаты в виде объекта словаря на total.htmlшаблон. Условное отображениеresult 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: для

Элемент в директиве 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-формы

<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 в браузере.

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

py: def

Эта директива используется для создания макроса. Макрос - это многократно используемый фрагмент кода шаблона. Как и функция 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://localhost:8080/macro

Следующий вывод будет отображаться в браузере -

py: с

Эта директива позволяет назначать выражения локальным переменным. Эти локальные переменные делают выражение внутри менее подробным и более эффективным.

Предполагая, что 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>

Содержимое другого 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-сценарий templates \ 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>

Вот код templates \ 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>

Перед запуском сервера убедитесь, что в папке шаблонов есть заголовки.html, main.html и footer.html. Войтиhttp://localhost:8082/refinclude в браузере, чтобы получить следующий результат

В @expose()декоратор по умолчанию отображает html-контент. Однако это может быть установлено наjson content type. 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, за исключением того факта, что он предоставляет ответ приложения / 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"});

Иногда веб-приложению может потребоваться структура URL-адреса, имеющая более одного уровня. TurboGears может просматривать иерархию объектов, чтобы найти подходящий метод, способный обработать ваш запрос.

Проект, «начатый» с помощью gearbox, имеет класс BaseController в папке проекта lib. Он доступен как «Hello / hello / lib / base.py». Он служит базовым классом для всех субконтроллеров. Чтобы добавить подуровень URL-адреса в приложение, создайте подкласс под названием BlogController, производный от BaseController.

Этот BlogController имеет две функции контроллера: index () и post (). Оба предназначены для предоставления по одному шаблону, blog.html и post.html.

Note - Эти шаблоны помещаются в подпапку - 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 введен, он выдаст следующий результат -

Одним из наиболее важных аспектов любого веб-приложения является представление пользовательского интерфейса пользователю. 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.forms

Он содержит класс Form, который действует как основа для настраиваемых форм. Существует класс TableForm, который полезен при отображении полей в таблице с двумя столбцами. ListForm представляет свои поля в виде неупорядоченного списка.

Sr.No. Поля и описание
1

TextField

Однострочное поле ввода текста

2

TextArea

Поле ввода многострочного текста

3

CheckBox

Представляет проверяемый прямоугольный ящик с этикеткой

4

CheckBoxList

Флажки группы pf с множественным выбором

5

RadioButton

Кнопка переключения для выбора / отмены выбора

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

Ползунок числа

В следующем примере создается форма, использующая некоторые из этих виджетов. Хотя большинство этих виджетов определены в 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 - это текстовое поле, которое может принимать только цифры. Стрелки вверх и вниз создаются на правой границе, чтобы увеличивать или уменьшать число внутри нее. Начальное значение также можно указать в качестве аргумента в конструкторе.

twf.NumberField(value)

Справа от поля CalendarDatePicker отображается кнопка календаря. При нажатии всплывает селектор даты. Пользователь может вручную ввести дату в поле или выбрать дату в селекторе даты.

twd.CalendarDatePicker()

Объект EmailField представляет собой TextField, но текст в нем должен быть в формате электронной почты.

EmailID = twf.EmailField()

Следующая форма также имеет RadioButtonList. Конструктор этого класса содержит объект List как значение параметра options. Будет отображен переключатель для каждой опции. Выбор по умолчанию определяется параметром значения.

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 у нас есть stipulated/save_formкак URL-адрес действия. Следовательно, добавьтеsave_form() функция в RootController.

@expose()
def save_movie(self, **kw):
   return str(kw)

Убедитесь, что сервер работает (с помощью коробки передач). Войтиhttp://localhost:8080/twform в браузере.

Нажатие кнопки отправки отправит эти данные в save_form() URL-адрес, который отобразит данные формы в виде объекта словаря.

{
   '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'
}

В хорошей библиотеке виджетов Forms должна быть функция проверки ввода. Например, пользователя следует заставить ввести данные в обязательное поле или проверить, содержит ли поле электронной почты действительный адрес электронной почты, не прибегая к каким-либо другим программным средствам (например, функциям JavaScript) для проверки.

Ранние версии библиотеки форм ToscaWidgets, которые полагались на модуль FormEncode для поддержки проверки. ToscaWidgets2 теперь имеет встроенную поддержку проверки, доступную в модуле tw2.core. Однако по-прежнему можно использовать методы проверки FormEncode.

Для проверки формы ToscaWidgets используется декоратор @validate.

@validate(form, error_handler, validators)
  • В ’form’ - проверяемый объект формы ToscaWidgets.

  • В ‘error-handler’ это метод контроллера, используемый для обработки ошибок формы.

  • В ‘validators’ являются объектом словаря, содержащим валидаторы FormEncode.

Типы валидаторов

Модуль tw2.core содержит класс валидатора, от которого унаследованы другие валидаторы. Также на его основе можно разработать собственный валидатор. Некоторые из важных валидаторов описаны ниже -

LengthValidator- Проверьте, имеет ли значение заданную длину. Минимальные и максимальные пределы определяются с помощью параметров min и max. Пользовательские сообщения для длины ниже и выше 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 предоставляет очень удобную систему обмена сообщениями для ненавязчивого уведомления пользователя. Класс 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, выполняет перенаправление, то флэш-память будет видна внутри перенаправленной страницы. Если метод напрямую предоставляет шаблон, то флэш-память будет видна внутри самого шаблона.

Внешний вид флэш-сообщения можно настроить, применив стили CSS к коду состояния. «Быстрый запуск» проекта содержит коды состояния ошибок, предупреждений, информации и ОК, настроенные с помощью таблицы стилей 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

Используется как flash template при рендеринге.

4

flash.allow_html

Повороты on/off escaping in flash messages, по умолчанию HTML не разрешен.

5

flash.js_call

Код JavaScript, который будет запускаться при отображении flash из JavaScript. По умолчаниюwebflash.render()

6

flash.js_template

string.Template Экземпляр используется для замены полной поддержки JavaScript для флеш-сообщений.

  • pop_payload() - функция fetches current flash message, statusи сопутствующая информация. При получении флэш-сообщения файл cookie будет удален.

  • render(container_id, use_js=True) - Визуализируйте флэш-сообщение внутри шаблона или предоставьте для них поддержку Javascript.

  • container_id - это DIV, в котором будут отображаться сообщения, в то время как use_js переключает между рендерингом flash в формате HTML или для использования JavaScript.

  • status - Получить только текущий статус флеш-памяти, получение статуса флеш-памяти удалит cookie.

  • message - Получить только текущее флэш-сообщение, получение флэш-сообщения удалит 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 могут поддерживаться файловой системой, базой данных или значениями хешированных файлов cookie. Небольшой объем данных сеанса обычно хранится в файлах cookie, но для большего объема данных сеанса используется MemCache.

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

Стакан в управлении сеансом

TurboGears использует Beaker для управления сеансом. Проект, запускаемый с помощью gearbox, по умолчанию настроен на использование хешированных файлов cookie для хранения данных сеанса.

Каждый раз, когда клиент подключается, промежуточное программное обеспечение сеанса (Beaker) проверяет файл cookie, используя имя файла cookie, которое было определено в файле конфигурации. Если cookie не найден, он будет установлен в браузере. При всех последующих посещениях промежуточное ПО находит файл cookie и использует его.

Чтобы включить управление сеансом, класс сеанса должен быть включен в проект следующим оператором импорта -

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 предоставляет два типа методов кэширования:

Whole-page Caching

Он работает на уровне протокола HTTP, чтобы избежать полных запросов к серверу, если браузер пользователя или промежуточный прокси-сервер (например, Squid) перехватит запрос и вернет кэшированную копию файла.

Application-level Caching

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

Кэширование на уровне приложений

Как упоминалось ранее, проект TurboGears с быстрым запуском настроен для включения поддержки кэширования пакета Beaker. Beaker поддерживает следующие серверы, используемые для хранения кеша:

  • memory- Используется для хранения по процессам. Это очень быстро.

  • filesystem - хранилище для каждого процесса, а также для нескольких процессов.

  • DBM database - на процесс, на несколько процессов, довольно быстро.

  • SQLAlchemy database- хранилище на сервере базы данных. Медленнее по сравнению с приведенными выше вариантами.

  • Memcached - кеш-память на базе многосерверной памяти.

Кэширование контроллера

Для быстрого кэширования контроллера cached()декоратор доступен. Все тело контроллера кэшируется в зависимости от различных параметров запроса. Определениеtg.decorators.cached() декоратор выглядит следующим образом

tg.decorators.cached(key, expire, type, 
   query-args, cache_headers, invalidate_on_startup, cache_response)

Описание параметров следующее -

Sr.No. Параметры и описание
1

key

Задает параметры контроллера, используемые для генерации ключа кеша.

2

expire

Время в секундах до истечения срока действия кеша, по умолчанию - «никогда».

3

Type

dbm, memory, file, memcached или None.

4

cache_headers

Кортеж имен заголовков, указывающий заголовки ответа.

5

invalidate_on_startup

Если True, кеш становится недействительным при каждом запуске или перезапуске приложения.

6

cache_response

ответ должен быть кэширован или нет, по умолчанию - True.

Ниже приведен пример кеширования контроллера -

@cached(expire = 100, type = 'memory')
@expose()
def simple(self):
   return "This is a cached controller!"

Кэширование на уровне шаблона

Механизм шаблонов Genshi извлекает шаблон из кеша, если его содержимое не изменилось. По умолчанию размер этого кэша равен 25. По умолчанию автоматическая перезагрузка шаблонов истинна. Для повышения производительности вapp_cfg.py -

[app:main]
genshi.max_cache_size = 100
auto_reload_templates = false

Чтобы кэшировать шаблон, вам просто нужно вернуть tg_cache параметр от контроллера, который отображает кэшированный шаблон.

Tg_cache - это словарь, который принимает следующие ключи:

  • key - Ключ кеша. Default: Никто.

  • expire - как долго кеш должен оставаться в живых. Default: никогда не заканчивается

  • type - память, dbm, memcached. Default: dbm.

В следующем примере показано кеширование шаблона -

@expose(hello.templates.user')
def user(self, username):
   return dict(user = username, tg_cache = dict(key = user, expire = 900))

Хотя можно использовать SQL в приложении TurboGears для выполнения операций CRUD с любой реляционной базой данных, рекомендуется использовать SQLAlchemy, набор инструментов Python - это мощный объектно-реляционный сопоставитель, который дает разработчикам приложений полную мощность и гибкость SQL. Помимо поддержки баз данных на основе SQL через SQLAlchemy, TurboGears также поддерживает базу данных MongoDB через Ming. В этом разделе обсуждается функциональность SQLAlchemy.

Что такое ORM (объектно-реляционное сопоставление)?

Большинство платформ языков программирования являются объектно-ориентированными. С другой стороны, данные на серверах СУБД хранятся в виде таблиц. Сопоставление объектных отношений - это метод сопоставления параметров объекта с базовой структурой таблицы СУБД. ORM API предоставляет методы для выполнения операций CRUD без необходимости писать необработанные операторы SQL.

Когда проект TurboGears создается с помощью команды 'quickstart' из набора инструментов gearbox, поддержка SQLAlchemy включается по умолчанию следующими параметрами конфигурации:

config['use_sqlalchemy'] = True
config['sqlalchemy.url'] = 'sqlite:///devdata.db'

«Быстрый запуск» проекта также создает в нем пакет моделей. Например, проект Hello будет иметь Hello \ hello \ model. В этом пакете созданы следующие файлы -

  • __init__.py- Здесь настраивается доступ к базе данных. В этот модуль импортируются объекты модели приложения. Он также имеет DBSession - глобальный менеджер сеансов, а также DeclarativeBase, который является базовым классом для всех классов модели.

  • auth.py- Здесь определяются модели, используемые стеком аутентификации. Дополнительные модели баз данных хранятся в этом пакете как отдельный модуль и добавляются в __init__.py.

Давайте добавим модель ученика, которая создаст стол ученика в нашем sqlite база данных.

Hello\hello\model\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.

Следующие методы сеанса выполняют операции CRUD -

  • DBSession.add(model object) - вставляет запись в отображаемую таблицу.

  • DBSession.delete(model object) - удаляет запись из таблицы.

  • DBSession.query(model).all() - извлекает все записи из таблицы (соответствует запросу SELECT).

Вы можете применить фильтр к полученному набору записей с помощью атрибута filter. Например, чтобы получить записи с city = 'Hyderabad' в таблице студентов, используйте следующий оператор -

DBSession.query(model.student).filter_by(city = ’Hyderabad’).all()

Теперь мы увидим, как взаимодействовать с моделями через URL-адреса контроллеров.

Сначала давайте разработаем форму ToscaWidgets для ввода данных студента.

Hello\hello\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в браузере после запуска сервера. В браузере откроется следующая форма информации о студенте -

Вышеуказанная форма предназначена для отправки в ‘/save_record’URL. Следовательноsave_record() функцию необходимо добавить в root.pyвыставить его. Данные из формы ученика принимаются этой функцией как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")

Обратите внимание, что после успешного добавления браузер будет перенаправлен на ‘/listrec’ URL. Этот URL предоставляетсяlistrec() function. Эта функция выбирает все записи в таблице студентов и отправляет их в форме объекта 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. Также появится сообщение «новая запись успешно добавлена».

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>

Следующие табличные данные будут отображаться, когда http://localhost:8080/showlist URL вводится в браузере -

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 создается со следующим кодом -

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 предоставляет расширение tgext.admin, которое поддерживается tgext.crud и sprox. Этот Sprox - это пакет, используемый для создания веб-виджетов непосредственно из схемы базы данных. Это можно использовать для автоматического создания простых страниц администрирования и является набором инструментов для страницы / admin в недавно запущенных приложениях.

По умолчанию администратор предоставит автоматически сгенерированный доступ ко всем моделям, импортированным в ваш проект models / __ init__.py.

Как создать администратора TurboGears

Администратор 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)

Войдите в приложение для быстрого запуска после запуска сервера и посетив http://localhost:8080/loginа затем введите учетные данные менеджера, как показано выше. Браузер отобразит страницу администратора, подобную показанной ниже -

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

Кнопка «Новый» в верхней части этой сетки данных позволяет добавить запись. Точно так же кнопки действий для редактирования и удаления записи также представлены в столбце действий этой таблицы данных. Также отображается поле поиска для условного выбора записей.

Приложение 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

All

Проверить, соблюдены ли все указанные предикаты

2

Any

Проверить, выполняется ли хотя бы один из указанных предикатов

3

is_user

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

4

in_group

Убедитесь, что пользователь принадлежит к определенной группе.

5

in_all_groups

Убедитесь, что пользователь принадлежит ко всем указанным группам.

6

in_any_group

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

7

is_anonymous

Убедитесь, что текущий пользователь анонимен.

8

has_permission

Убедитесь, что текущий пользователь имеет указанное разрешение.

9

has_all_permissions

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

10

has_any_permission

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

Например, если у вас есть предикат, grant access user belonging to customers group, то вы можете использовать следующую встроенную проверку предикатов -

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. Он использует Ming, API-интерфейс Object Document Mapper. Использование Ming очень похоже на SQLAlchemy. Язык запросов Ming позволяет переносить проект TurboGears на основе SQLAlchemy в Ming.

Что такое PyMongo

PyMongo - это дистрибутив Python, содержащий инструменты для работы с MongoDB. Ming расширяет PyMongo, обеспечивая -

  • Декларативные модели
  • Проверка и преобразование схемы
  • Схема эволюции
  • Чистая реализация MongoDB InMemory
  • Единица работы
  • Карта идентичности
  • Отношения один-ко-многим, многие-к-одному и многие-ко-многим

Прежде всего, вам необходимо скачать и установить MongoDB. Последний дистрибутив MongoDB можно скачать сhttps://www.mongodb.org/downloads

В Windows запустите сервер MongoDB, указав параметр -dbpath -

C:\mongodb\bin>Mongod --dbpath d:\mongo

D:\mongo folderпредназначен для хранения базы данных 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 - Вот где databaseдоступ настроен. Ваши коллекции должны бытьimported into this module. Например, мы добавим в этот пакет студенческую коллекцию.

  • session.py - Этот файл определяет session of your database connection. Вам нужно будет импортировать это каждый раз, когда вам нужно будет объявитьMappedClass указать сеанс для perform queries.

  • auth.py - Этот файл будет создан, если у вас есть enabled authentication and authorizationв кратком руководстве. Он определяет три коллекцииrepoze.who, который в дальнейшем зависит от: пользователя, группы и разрешения.

Определение вашей коллекции

По умолчанию TurboGears настраивает Ming в декларативном режиме. Это похоже на декларативную поддержку SQLAlchemy и требует, чтобы каждая модель наследовала от класса MappedClass.

MappedClass требует, чтобы внутри был доступен подкласс __mongometa__, который дополнительно предоставляет подробные сведения об имени коллекции, в которой хранятся документы, и сеансе, используемом для хранения документов.

MappedClass также содержит определение полей в документе. В модуле odm Минга есть определения различных типов свойств поля -

  • FieldProperty
  • ForeignIdProperty
  • RelationProperty

В ming.schema module определяет следующие типы данных -

  • 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.

Привет \ 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 -

Gearbox serve –reload –debug

Откройте домашнюю страницу этого приложения (http://localhost:8080/)и войдите с учетными данными менеджера. Страница администратора этого приложения покажет список настроенных моделей. (войти как менеджер, пароль managepass)

Создание коллекций также можно проверить в веб-интерфейсе 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-адресе '/ add' приложения Rootcontroller, который вызывает функцию 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")

В папке шаблонов создаются следующие шаблоны -

Привет \ templates \ 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>

Привет \ templates \ 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 в браузере -

Каждый раз, когда данные добавляются и нажимается кнопка отправки, будет отображаться список текущих записей.

Набор инструментов Gearbox содержит команду scaffold, которая очень полезна для быстрого создания новых компонентов приложения TurboGears. Приложение, созданное с помощью команды быстрого запуска коробки передач, имеет шаблон скелета в папке модели (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']

Теперь пользователи могут вносить изменения в структуру таблицы в соответствии с их требованиями, а затем импортировать ее внутрь. model/__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 file в папке шаблонов будет следующее -

<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 есть три способа включить поведение в существующие приложения.

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

  • Controller Wrapper- Он находится между TurboGears и контроллером, поэтому контроллер можно расширить как декоратор. Таким образом, его можно прикрепить к любому стороннему приложению контроллера.

  • Application Wrapper - Он похож на любое промежуточное ПО WSGI, но работает только в контексте TurboGears.

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

Крючки

Хуки - это события, зарегистрированные в файле конфигурации приложения. app_cfg.py. Затем любой контроллер подключается к этим событиям декораторами событий.

Следующие крючки определены в TurboGears -

Sr.No. Крючки и описание
1

Startup()

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

2

shutdown()

только для всего приложения, вызывается при выходе из приложения.

3

configure_new_app

новое приложение создано конфигуратором приложений.

4

before_config(app)

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

5

after_config(app)

только для всего приложения, вызывается после завершения настройки.

6

before_validate

Вызывается перед выполнением проверки

7

before_call

Вызывается после проверки перед вызовом фактического метода контроллера.

8

before_render

Вызывается перед отрисовкой шаблона контроллера, output - это возвращаемое контроллером значение.

9

after_render

Вызывается после завершения рендеринга шаблона контроллера.

Зарегистрировать крючок

Чтобы register a Hook, создавать функции в 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 обозначаются tgext.* package. Инструментарий Gearbox предоставляет команду tgext для создания образца расширения. Например -

gearbox tgext -n myextension

Другие необязательные параметры для этой команды:

  • --author - имя автора пакета.

  • --email - емейл автора пакета.

  • --licence- лицензия, используемая для пакета. По умолчанию - MIT.

  • --description - Описание упаковки.

  • --keywords - Ключевые слова пакета (по умолчанию: turbogears2.extension).

Это создаст каталог tgext.myextension, внутри которого есть простой пример расширения.

Run the setup.py внутри каталога -

Python setup.py install

В _init_.py файл внутри tgext/myextension папка содержит -

  • Plugme function - Это точка входа в расширение.

  • SetupExtension class - здесь происходит инициализация расширения.

  • On_startup function - внутри класса находится ловушка, зарегистрированная в функции __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)

Если мы запустим сервер с помощью команды сервера gearbox, уведомление о новом зарегистрированном расширении можно будет просмотреть на консоли следующим образом:

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

Если вашему расширению необходимо предоставлять модели и контроллеры, вы, вероятно, захотите взглянуть на Pluggable Applications, которые предназначены для создания многоразовых приложений Turbogears, которые можно подключать к другим приложениям для расширения их возможностей.

Используйте следующую команду коробки передач, чтобы создать подключаемое приложение -

gearbox quickstart-pluggable plugtest

Эти подключаемые приложения могут определять свои собственные -

  • Controllers - который будет автоматически смонтирован при очистке приложения.

  • Models - который будет доступен внутри и вне подключенного приложения.

  • Helpers - которые могут быть автоматически представлены в объекте «H» в шаблоне приложения.

  • Bootstrap - который будет выполнен при вызове setup-app.

  • Statics - которые будут доступны по их собственному частному пути.

Установите это приложение plugtest и смонтируйте его, внеся следующие изменения в app_cfg.py.

from tgext.pluggable import plug
plug(base_config, plugtest)

REST означает REпрезентационный Sтейт Tперевод. REST - это архитектура, основанная на веб-стандартах и ​​использующая протокол HTTP для передачи данных. Он вращается вокруг ресурса, где каждый компонент является ресурсом, а доступ к ресурсу осуществляется через общий интерфейс с использованием стандартных методов HTTP. REST был впервые представленRoy Fielding in 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/students он предоставит список наших студентов в формате json.

Мы используем метод публикации, чтобы определить, как мы собираемся сохранить нашего ученика в базе данных. Этот метод вызывается всякий раз, когда http://localhost:8080/student URL-адрес доступен с помощью запроса 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.

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 под Circus and Chaussette

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

TurboGears - GoogleAppEngine

Установите SDK Google AppEngine для 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 в консоли разработчика. Теперь нажмите кнопку развертывания в панели запуска. После завершения процесса развертыванияhttp://mytgapp.appspot.com/ посетите, чтобы просмотреть нашу заявку в Интернете.