Cherrypy на русском


CherryPy — Википедия (с комментариями)

Материал из Википедии — свободной энциклопедии

К:Википедия:Статьи без изображений (тип: не указан)

CherryPy (/ˈʧɛɹi paɪ/ «ЧерриПай», игра слов: англ. cherry pie — «вишнёвый пирог») — объектно-ориентированный веб-фреймворк, написанный на языке программирования Python. Спроектирован для быстрой разработки веб-приложений для сети Интернет. Представляет собой надстройку над HTTP-протоколом, но остаётся на низком уровне и не выходит за рамки требований RFC [www.faqs.org/rfcs/rfc2616.html 2616].

CherryPy может выступать в качестве самостоятельного веб-сервера или работать под управлением другого серверного приложения, поддерживающего протокол WSGI. CherryPy не занимается такими задачами, как обработка шаблонов для вывода данных, доступ к базе данных, авторизация пользователя. Фреймворк расширяется за счёт фильтров, простых интерфейсов, состоящих из семи функций, которые вызываются в определённых точках процесса обработки запросов/ответов.

CherryPy является главным компонентом TurboGears.

«Pythonic style»-интерфейс

Одной из целей основателя проекта Реми Делона было сделать CherryPy максимально соответствующей принципу «pythonic style». Это позволило разработчикам использовать фреймворк как любой обычный модуль Python и не думать об особенностях веб-программирования.

Для примера, так выглядит стандартный Hello World в СherryPy 3:

import cherrypy class HelloWorld(object): def index(self): return "Hello World!" index.exposed = True cherrypy.quickstart(HelloWorld())

Напишите отзыв о статье "CherryPy"

Примечания

  1. ↑ [pypi.python.org/pypi/CherryPy/5.1.0 CherryPy 5.1.0 : Python Package Index]

Ссылки

Отрывок, характеризующий CherryPy

Возвратившись со смотра, Кутузов, сопутствуемый австрийским генералом, прошел в свой кабинет и, кликнув адъютанта, приказал подать себе некоторые бумаги, относившиеся до состояния приходивших войск, и письма, полученные от эрцгерцога Фердинанда, начальствовавшего передовою армией. Князь Андрей Болконский с требуемыми бумагами вошел в кабинет главнокомандующего. Перед разложенным на столе планом сидели Кутузов и австрийский член гофкригсрата. – А… – сказал Кутузов, оглядываясь на Болконского, как будто этим словом приглашая адъютанта подождать, и продолжал по французски начатый разговор. – Я только говорю одно, генерал, – говорил Кутузов с приятным изяществом выражений и интонации, заставлявшим вслушиваться в каждое неторопливо сказанное слово. Видно было, что Кутузов и сам с удовольствием слушал себя. – Я только одно говорю, генерал, что ежели бы дело зависело от моего личного желания, то воля его величества императора Франца давно была бы исполнена. Я давно уже присоединился бы к эрцгерцогу. И верьте моей чести, что для меня лично передать высшее начальство армией более меня сведущему и искусному генералу, какими так обильна Австрия, и сложить с себя всю эту тяжкую ответственность для меня лично было бы отрадой. Но обстоятельства бывают сильнее нас, генерал. И Кутузов улыбнулся с таким выражением, как будто он говорил: «Вы имеете полное право не верить мне, и даже мне совершенно всё равно, верите ли вы мне или нет, но вы не имеете повода сказать мне это. И в этом то всё дело». Австрийский генерал имел недовольный вид, но не мог не в том же тоне отвечать Кутузову. – Напротив, – сказал он ворчливым и сердитым тоном, так противоречившим лестному значению произносимых слов, – напротив, участие вашего превосходительства в общем деле высоко ценится его величеством; но мы полагаем, что настоящее замедление лишает славные русские войска и их главнокомандующих тех лавров, которые они привыкли пожинать в битвах, – закончил он видимо приготовленную фразу. Кутузов поклонился, не изменяя улыбки. – А я так убежден и, основываясь на последнем письме, которым почтил меня его высочество эрцгерцог Фердинанд, предполагаю, что австрийские войска, под начальством столь искусного помощника, каков генерал Мак, теперь уже одержали решительную победу и не нуждаются более в нашей помощи, – сказал Кутузов.

wiki-org.ru

Популярные фреймворки для Python | Блог о веб программировании

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

Django

Django это свободный веб-фреймворк на языке Python, который является наверно самым популярным веб-фреймворком на Python. Django следует шаблону программирования MVC (Model-View-Controller). Сайт на Django строится из одного или нескольких приложений, которые рекомендуется делать отчуждаемыми и подключаемыми. Главное преимуществ Django, отличающие его от своих конкурентов является хорошая документация в том числе и на русском языке.

Django поддерживает работу с основными базами данных — MySQL, PostgreSQL и Oracle. Он предоставляет уровень абстракции, который избавляет от необходимости писать SQL-запросы для получения/сохранения данных в базу данных. Все таблицы, использующиеся сайтом, описываются в виде классов в отдельном файле models.py. Далее при помощи методов этих классов, происходит манипуляция с содержимым таблиц. Таким образом, работа с базой данных становится полностью объектно-ориентированной.

Так же в Django есть встроенный интерфейс администратора, через который в удобной форме можно работать с контентом сайта.

Наверно поэтому он имеет самое крупное сообщество среди веб-фреймворков на Python.

TurboGears

Так же, как и Django, TurboGears был разработан для быстрого создания новостных сайтов. TurboGears это Python веб фреймворк, который состоит из нескольких составляющих компонент, таких как:

  • CherryPy для диспетчеризации url;
  • MochiKit для работы с Javascript;
  • SQLObject для работы с базой данных;
  • Kid для работы с шаблонами.

Из недостатков можно отметит — плохая совместимость 1.x и 2.x версий и не самая хорошая документация.

Pylons

Pylons представляет собой легкий веб-фреймворк который делает упор на гибкость и быстроту разработки. В настоящее время развитие Pylons завершено на версии 1.0 и дальнейшего существенного изменения не планируется.

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

Что касается документации, то Pylons ею абсолютно не занимается.

Zope

Zope представляет собой сервер веб-приложений, написанный на Python и предназначенный для создания систем управления контентом, интранет-приложений, порталов и прочих проектов. Zope расшифровывается как «Z Object Publishing Environment» (Среда Публикации Объектов Z). Особенностью Zope является объектно-ориентированность. Все данные представляются в виде компонентов, занимающих определенное место в общей иерархии и хранящихся во встроенной объектной базе данных — ZoBD. И поэтому программирование в Zope сводится к проектированию иерархии компонентов.

Русскоязычной документации по Zope практически нет.

Twisted

Twisted является фрэймворком для написания сетевых приложений на Python. Основывается на парадигме событийно-ориентированного программирования. Пользователь пишет функции обратного вызова, которые затем вызываются фреймворком. Он поддерживает множество протоколов, имеет модули для создания web-серверов, чат-клиентов и серверов, почтовых серверов, ssh-серверов.

Web2py

Бесплатный и с открытым кодом, полноценный фреймворк уровня предприятия для гибкой разработки веб-приложений для доступа к БД. Web2py позволяет создавать и разрабатывать приложения прямо в онлайне. В целом он очень похож на Django.

Webware

Webware для Python представляет собой набор Python пакетов для разработки объектно-ориентированных веб приложений.

CherryPY

CherryPy это объектно-ориентированный HTTP фреймвокр. Он представляет собой надстройку над http-протоколом и может выступать в качестве самостоятельного веб-сервера или работать под управлением другого серверного приложения, поддерживающего протокол WSGI. CherryPy не занимается обработкой шаблонов д, доступ к базе данных и авторизация пользователя.

Porcupine

Porcupine это Python сервер веб-приложений представляющий собой объектно-ориентированный фреймворк для быстрой разработки Богатых Интернет приложений (Rich Internet Applications).

Karrigell

Karrigell это фреймворк для работы с БД в среде Python. Он работает как веб-сервер и база данных Python (PyDbLite), но может работать и с другими базами данных.

Flask

Микро веб-фреймворк на языке Python построеный на Werkzeug и Jinja2

Bottle

Ещё один быстрый и простой микро веб-фреймворк для Python.

Pysi

Как пишет автор фреймворка: Pysi — это фреймворк «для себя». Если кодите на заказ, увидите лишь «ещё один фреймворк».Основное качество pysi — производительность.Второе по важности — простота.

world-blog.ru

CherryPy рабочее приложение

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

Рассмотрим приложения Python как web2py рамок; весь проект / приложение создается в терминах структуры MVC. Точно так же, CherryPy позволяет пользователю установить и настроить расположение кода в соответствии с их требованиями.

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

Файловая система

Файловая система приложения показан на следующем снимке экрана -

Вот краткое описание различных файлов, которые мы имеем в файловой системе -

  • config.py - Каждое приложение нуждается в конфигурационный файл и способ ее загрузки.Эта функция может быть определена в config.py.

  • controllers.py - MVC является популярным шаблон дизайна за которым следуют пользователи.Controllers.py где все объекты реализуются , которые будут установлены наcherrypy.tree.

  • models.py - Этот файл взаимодействует с базой данных непосредственно для некоторых услуг или для хранения постоянных данных.

  • server.py - Этот файл взаимодействует с производством готовых веб - сервер , который работает должным образом с балансировки нагрузки прокси.

  • Static - Она включает в себя все CSS и графические файлы.

  • Просмотров - Она включает в себя все файлы шаблона для данного приложения.

пример

Давайте подробно узнать шаги по созданию приложения CherryPy.

Шаг 1 - Создание приложения , которое должно содержать приложение.

Шаг 2 - Внутри каталога, создать пакет питона , соответствующий проект.Создание каталога GEdit и включают в себя _init_.py файл в то же самое.

Шаг 3 - Внутри упаковки, включают в себя controllers.py файл со следующим содержанием -

#!/usr/bin/env python import cherrypy class Root(object): def __init__(self, data): self.data = data @cherrypy.expose def index(self): return 'Hi! Welcome to your application' def main(filename): data = {} # will be replaced with proper functionality later # configuration file cherrypy.config.update({ 'tools.encode.on': True, 'tools.encode.encoding': 'utf-8', 'tools.decode.on': True, 'tools.trailing_slash.on': True, 'tools.staticdir.root': os.path.abspath(os.path.dirname(__file__)), }) cherrypy.quickstart(Root(data), '/', { '/media': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'static' } }) if __name__ == '__main__': main(sys.argv[1])

Шаг 4 - Рассмотрим приложение , в котором пользователь вводит значение через форму.Давайте включать в себя две формы - index.html и submit.html в приложении.

Шаг 5 - В приведенном выше коде для контроллеров, мы имеем индекс (),которая является функцией и загружает по умолчанию первый , если конкретный контроллер называется.

Шаг 6 - Осуществление индексногометода()может быть изменен следующим образом -

@cherrypy.expose def index(self): tmpl = loader.load('index.html') return tmpl.generate(title='Sample').render('html', doctype='html')

Шаг 7 - Это позволит загрузить index.html на запуск данного приложения и направить его к данному потоку вывода.Файл index.html выглядит следующим образом -

index.html

<!DOCTYPE html > <html> <head> <title>Sample</title> </head> <body class = "index"> <div id = "header"> <h2>Sample Application</h2> </div> <p>Welcome!</p> <div id = "footer"> <hr> </div> </body> </html>

Шаг 8 - Важно , чтобы добавить метод к классу Root в controller.py, если вы хотите , чтобы создать форму , которая принимает значения , такие как имена и названия.

@cherrypy.expose def submit(self, cancel = False, **value): if cherrypy.request.method == 'POST': if cancel: raise cherrypy.HTTPRedirect('/') # to cancel the action link = Link(**value) self.data[link.id] = link raise cherrypy.HTTPRedirect('/') tmp = loader.load('submit.html') streamValue = tmp.generate() return streamValue.render('html', doctype='html')

Шаг 9 - код , который будет включен в submit.html выглядит следующим образом -

<!DOCTYPE html> <head> <title>Input the new link</title> </head> <body class = "submit"> <div id = " header"> <h2>Submit new link</h2> </div> <form action = "" method = "post"> <table summary = ""> <tr> <th><label for = " username">Your name:</label></th> <td><input type = " text" id = " username" name = " username" /></td> </tr> <tr> <th><label for = " url">Link URL:</label></th> <td><input type = " text" name= " url" /></td> </tr> <tr> <th><label for = " title">Title:</label></th> <td><input type = " text" name = " title" /></td> </tr> <tr> <td></td> <td> <input type = " submit" value = " Submit" /> <input type = " submit" name = " cancel" value = "Cancel" /> </td> </tr> </table> </form> <div id = "footer"> </div> </body> </html>

Шаг 10 - Вы получите следующий вывод -

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

Если метод включает в себя метод "GET", значения, которые будут сохранены будут видны в URL.

www.w3ii.com

Web development with CherryPy

Introduction

Note:

  1. Since I'm just beginning with CherryPy, most of the stuff below is excerpts from the site's documentation. Too lazy to put references everywhere :-)
  2. This article was originally written in 2004, before 0.9 came out. As of July 2006, CherryPy is now 2.x.

TurboGears

Setup

Here's how to get up and running with CherryPy using its embedded HTTP server, which is good enough for testing purposes:

  1. Download and unzip the latest stable version
  2. python setup.py install
  3. cd cherrypy/tutorial/
  4. python tut01_helloworld.py
  5. Aim your browser at http://localhost:8080

    If 8080 is already in use, edit to use another port.

Pros and Cons

Pros

  • Small, yet powerful
  • Less abstract than Zope, closer to Python
  • Simple but sufficient templating language
  • Easier access to the source code as it lives on the filesystem instead of inside the ZODB (ie. no need to use FTP or WebDAV to edit files with one's favorite text editor, and source code can be watched with an SCM)
  • Good documentation for newbies
  • Includes its own web server, whose performance can be improved by allowing it to spawn multiple processes or threads to handle more than one request simultaneously. Makes it easier for newbies to take a quick look instead of having to worry about making CherryPy work with a foreign web server right from the start
  • Come to think of it, it makes more sense to map sub-directories into calls to methods located in classes, instead of scattering code into multiple sub-directories on the filesystem.

    In other words, users don't care whether http://localhost/sub/index is a call to a file named index actually located in the web server's docs/sub/, or just a call to a method named index() in a class named Sub

Cons

Structure of a CherryPy source file

A Python script written in CherryPy consists in one or more sections:

use SomeOtherSourceFile #If you need to share code between code between several source files   #An abstract class can only be derived. Useful to share stuff CherryClass Root abstract:aspect:     #Add AOP stuff here variable:     # Class variables here function:     #One or more functions to handle logic mask:     #One or more masks to handle display in CHTL or CGTLview:     #One or more views to link masks and functions     # A view should always return a string

Note that a function cannot be "called" directly from a browser. Only views and masks, which return some rendered data, can be "called" directly.

CherryPy sits between an application server and a compiler. You write source files, compile them with CherryPy and CherryPy generates an executable containing everything to run the website (including an HTTP server)

Like a compiler, it reads input files and generates an executable. The executable contains everything to run the website, including its own HTTP server.

Like an application server, it delivers highly-dynamic web sites that can be linked to other ressources, like a database for instance.

In a server generated by CherryPy, every request from a client (for instance, a browser requesting an URL) to a "directory" is transformed into a call to the method of a class which corresponds to this directory. For instance, http://localhost/support/index is actually a call to the method "index" in the class Support, which can either be a stand-alone class, or (usually) derived from the Root class where you will put stuff that is common among all parts of your application. The parameters sent by the client become the arguments of the function.

Hello world (static)

  1. Unpack the CherryPy package somewhere
  2. Create a directory somewhere (eg. C:\TMP)
  3. From the CherryPy package, copy the src/ sub-directory (eg. C:\TMP\SRC; Only needed to compile, but not needed to run a compiled server.) Later, when you use additional modules via the "use" command, you will also need to copy the lib/ directory into eg. C:\TMP\LIB
  4. In the main directory, create a sub-directory hello/ (ie. C:\TMP\HELLO)
  5. From the CherryPy package, copy cherrypy.py into C:\TMP\HELLO
  6. In C:\TMP\HELLO, create a file named hello.cpy with the following content:

    CherryClass Root:mask:    def index(self):        <html><body>            Hello, world !        </body></html> 

  7. Still in C:\TMP\HELLO, run "python cherrypy.py hello.cpy" (without the quotes.) This generates helloServer.py
  8. Run this file with "python helloServer.py", which launches a web server on TCP 8000
  9. Aim your browser at http://localhost:8000
  10. To kill the running server, just close the DOS box

Thus, the URL http://localhost:8000/ triggers a call to the index method of the Root class. This means that http://localhost/page and http://localhost/root/page are perfectly equivalent.

The executable generated by CherryPy turns "CherryClass Root" into an instance of the class with a lower-case first letter (ie. root). Therefore, CherryClass names should always start with an upper case letter. This instance is a global variable and can be acces from anywhere in the program.

Hello world (dynamic)

This example uses CHTL tags to add dynamic stuff. Create and compile the following hello2.py file, and launch the program as previously explained:

CherryClass Root: mask:     def index(self, name="you"):         <html><body>             Hello, <b py-eval="name"></b> !             <form py-attr="request.base" action="" method="get">                 Enter your name: <input name=name type=text><br>                 <input type=submit value=OK>             </form>         </body></html>

CHTL and CGTL

CherryPy comes with two templating languages: CHTL (CherryPy HTML Templating Language; Web designers-friendly) and CGTL (CherryPy Generic Templating Language; Cannot be edited safely with WYSIWYG HTML editors). CHTL can be edited safely in a WYSIWYG HTML editor but is a bit more verbose than CGTL, which can only be edited safely in a text editor.

Both CHTL and CGTL only use 6 tags: py-eval, py-attr, py-exec, py-code, py-if (with py-else) and py-for. Note that you can NEVER use double-quotes inside the Python code (even with a backslash before). If you need to put some double-quotes in a string, use chr(34)

py-include

Used to insert the content of an external file. Very convenient to let designers play with HTML, and keep the mask section tidy. Here's a sample in CGTL:

CherryClass Root: mask:         def index(self):             <py-include="main">

The CHTL equivalent would be <div py-include="main">header</div> .

Note: The external file must actually have the extension ".cpyt", ie. although we're reffering to "main", this template must be named "main.cpyt".

To pass parameters from a method in a mask section to a template (ie. a .cpyt file containing CHTL or CGTL):

Caller (http://localhost/test/index)

CherryClass Test: mask:         def index(self,name='John'):                 <py-include="index">

Callee (http://localhost/test/index.cpyt)

<py-eval="name">

py-eval

An example in CHTL: This is a long string with a <div py-eval="'variable'"></div> in it.

In CGTL: <py-eval="2*2">

py-attr

<td py-attr="'red'" bgColor=""> is rendered as <td bgColor="red">

py-exec

Used to execute one line of Python code

py-code

Used to execute a block of Python code. Here's an example in CHTL:

<div py-exec="a=2"></div> <div py-code="     if a==2:         b=1     else:         b=2 "></div>

Its CGTL equivalent:

<py-exec="a=2"> <py-code="     if a==2:         b=1     else:         b==2 ">

py-if py-else

In CHTL:

<div py-if="1==1">     OK </div> <div py-else>     Not OK </div>

In CGTL:

<py-if="1==1">     OK </py-if> <py-else>     Not OK </py-else>

py-for

Note: In a py-for loop, CherryPy sets two handy special variables for you: _index and _end. The former is an integer containing the current number of iterations (from 0 to n-1). The latter contains the total number of iteration minus one.

in CHTL:

<div py-for="i in range(10)">     <div py-eval="i"></div> </div>

In CGTL:

<py-for="i in range(10)">     <py-eval="i"> </py-for>

Here's a bigger sample in CHTL. The main page displays a link which is a call to the embedded webColor() function. request is a global variable set by CherryPy for each request of a client. It is an instance of a class with several variables. One of them is called base and contains the base URL of the website:

CherryClass Root: mask:     def index(self):         <html><body>             <a py-attr="request.base+'/webColors'" href="">                 Click here to see a nice table with all web colors             </a>         </body></html>       def webColors(self):         <html><body>             <div py-exec="codeList=['00', '33', '66', '99', 'CC', 'FF']"></div>             <table border=1>             <div py-for="r in codeList">                 <div py-for="g in codeList">                     <tr>                         <div py-for="b in codeList">                             <div py-exec="color='#%s%s%s'%(r,g,b)"></div>                             <td py-attr="color" bgColor="" py-eval="'&nbsp;&nbsp;'+color+'&nbsp;'"></td>                         </div>                     </tr>                 </div>             </div>         </body></html>

Masks, Functions, Views, Aspect

Here's an example to display a list of books in the form of links. When a user clicks on one of the titles, the script returns the details of this book:

CherryClass Root: variable:     bookListData=[         ('Harry Potter and the Goblet of Fire', 'J. K. Rowling', '9$'),         ('The flying cherry', 'Remi Delon', '5$'),         ('I love cherry pie', 'Eric Williams', '6$'),         ('CherryPy rules', 'David stults', '7$')     ]   function:     def getBookListData(self):         return self.bookListData       def getBookData(self, id):         return self.bookListData[id]   mask:     def index(self):         <html><body>             Hi, choose a book from the list below:<br>             <py-for="title, dummy, dummy in self.getBookListData()">                 <a py-attr="'displayBook?id=%s'%_index" href="" py-eval="title"></a><br>             </py-for>         </body></html>       def displayBook(self, id):         <html><body>             <py-exec="title, author, price=self.getBookData(int(id))">             Details about the book:<br>             Title: <py-eval="title"><br>             Author: <py-eval="author"><br>             Price: <py-eval="price"><br>         </body></html>

Aspect

Aspect is based on AOP (Aspect oriented programming), which is a way to include code at the beginning or at the end of each of the methods of all derived classes. More info in Zen and the Art of Aspect-Oriented Programming. Here's a sample:

CherryClass NormalHeaderAndFooter: aspect:     (1) start:         _page.append("<html><body>I'm the header<br><br>")     (1) end:         _page.append("<br><br>I'm the footer</body></html>")   #Root derived from NormalHeaderAndFooter CherryClass Root(NormalHeaderAndFooter): mask:     def index(self):             Hello, world !     def otherPage(self):             I love cherry pie !

Start and End indicate the parts that will be added before and after each methods. The (1) is actually a condition, a way to include stuff only if the condition is true; In this example, the header and footer sections are added every time since the condition is always true (1). The condition can also be a Python expression to limit this action to only some methods, if you wish. In this case, the condition can include the type of methods (mask, view, variable) and/or its name (the name of the method to which this aspect will apply.) For instance, you can restrict a start aspect to such and such methods: function.name in ('index', 'edit') start: .

Here's the previous sample with extra conditions:

CherryClass NormalHeaderAndFooter: #This aspect part will not be included when calling yetAnotherPage() aspect:     (function.type=='mask' and function.name!='yetAnotherPage') start:         _page.append("<html><body>I'm the header<br><br>")     (function.type=='mask' and function.name!='yetAnotherPage') end:         _page.append("<br><br>I'm the footer</body></html>")   CherryClass Root(NormalHeaderAndFooter): mask:     def index(self):             Hello, world !     def otherPage(self):             I love cherry pie !     def yetAnotherPage(self):         <html><body bgcolor=red>             I love cherry pie !         </body></html>

Here, the aspect parts will be added before and after all methods... except yetAnotherPage(). If you get an "NameError: global name '_page' is not defined" when using aspect sections, read this.

Aspect is thought to work with mask sections, not with views, but there is way around this if you prefer to use views:

CherryClass Base: mask:         def header(self):             #Outsourced HTML to template             <py-include="header">           def mymain(self):             <py-include="main">   aspect:         (function.type=='view') start:                 myPage=[]                 myPage.append(self.header())   CherryClass Root(Base): view:         def index(self):                 myPage.append(self.mymain())

As Root is derived from Base, when the user hits http://localhost/, CherryPy first executes the aspect section of Base (here, it adds a header to the page by calling Base.header, and then executes Root.index which calls Base.mymain().

In the upcoming release 0.9, a new condition is function.isHidden, which restricts the condition to ... well, hidden functions :-)

Forms

Rmi is currently working on CherryObject to make forms easier to use. In the mean time, here's how to work with them.

The Form module defines four CherryClasses: FormField, FormSeparator, DefaultFormMask (Youll probably want to use your own masks for your own design), and Form.

Here's what those classes contain:

FormField

A FormField instance is used for each of the form fields.

function: __init__(label, name, typ, mask=None, mandatory=0, size=15, optionList=[], defaultValue='', validate=None)

FormSeparator

A FormSeparator instance is used to display some text or images between the different fields of the form.

function: __init__(label, mask)

DefaultFormMask

This CherryClass contains a default implementation of a mask for the fields. You'll probably want to use your own masks for your own design. The next section explains how to write your own field masks.

Here's how to customize how a text widget will be displayed:

if field.typ=='text':     result='%s: <input type=text name="%s" value="%s" size="%s">'%(         field.label, field.name, field.currentValue, field.size)     if field.errorMessage:         result+=' <font color=red>%s</font>'%field.errorMessage return result+'<br>'

Form

The is the main CherryClass of the module. To create a form, you should declare a CherryClass that inherits from Form.

  • variable: method
  • variable: enctype
  • variable: fieldList
  • function: formView(leaveValues=0)
  • function: validateFields()
  • function: setFieldErrorMessage(fieldName, errorMessage)
  • function: getFieldOptionList(fieldName)
  • function: getFieldDefaultValue(fieldName)
  • function: setFieldDefaultValue(fieldName, defaultValue)
  • function: getFieldNameList(exceptList=[])
  • function: validateForm()
  • view: postForm(**kw)

Here's a sample:

CherryClass Test(Form): function:     #Here, define the items to build the form     def __init__(self):         headerSep=FormSeparator('', defaultFormMask.defaultHeader)         textField=FormField(label='Text field:', name='textField', mandatory=1, typ='text')         selectField=FormField(label='Select field:', name='selectField', mandatory=1, typ='select', optionList=['Option 1', 'Option 2', 'Option 3'])         submitField=FormField(label='', name='Submit', typ='submit')         footerSep=FormSeparator('', defaultFormMask.defaultFooter)         self.fieldList=[headerSep, textField, selectField, submitField, footerSep]   mask:     # Here's the actual form     def index(self, **kw):         Here's the form:<br>         <py-eval="self.formView(0)">   view:     #This view automatically called when user submits form     #Overwrite this view and add your own code to handle the form data.     def postForm(self, **kw):         if self.validateForm():             res="<html><body>"             for key, value in kw.items():                 res+="%s : %s <br>"%(key, value)             return res+"</body></html>"         else:             return "<html><body><font color=red>Fill out missing fields</font>"+self.formView(1)+"</body></html>"

Sharing common stuff

To share elements, build an parent class, and derive this class in child classes. For instance:

####################### CherryClass ParentClass abstract: ####################### mask:     def header(self):         <html><body>             <center>                 Here's the header<p>       def footer(self):             and here's the footer                 </center>         </body></html>   ####################### CherryClass ChildClass(ParentClass): ####################### view:     def index(self):         page=self.header()                 page+="<h2>Hello World!</h2><p>"         page+=self.footer()         return page   ####################### CherryClass Root(ChildClass): #######################

If a project consists in mutliple but independent files, just compile them into a single server: python ../cherrypy.py Hello1.cpy Hello2.cpy Hello3.cpy . The resulting server will be named after the file source file, ie. Hello1Server.py, here.

If a source file depends on another, you just need to add the "use" keyword on the first line of the caller and compile the source files that do not include the "use" keyword, eg. if "Main.cpy" includes "use BoldTime", which is a reference to BoldTime.cpy, you just need to compile the caller source using "python cherrypy.py Main.cpy". Note that the "use" line must be on the very first line, with no comments preceding it. As usual with CherryPy, the class name starts with an upper-case letter (eg. BoldTime), but an instance of a class starts with a lower-case letter (eg. boldTime.myfunc).

If "use"d source files are located in a different directory from the caller scripts, either use the -I switch to tell CherryPy where to find those additional files (eg. python cherrypy.py -I /modules Main.cpy) or create and set an environment variable CHERRYPY_HOME (in which case, CherryPy will also look in CHERRYPY_HOME/lib and CHERRYPY_HOME/src for modules.)

Customizing a navigation bar in each section

Here's a tip given by Scott Luck to customize a navigation bar in each section of a site:

CherryClass PageLayout hidden: aspect:     ((function.type=='mask') and (not function.isHidden)) start:         _page.append("""Header""")         _page.append(str(self.appMenu()))       ((function.type=='mask') and (not function.isHidden)) end:         _page.append("""Footer""")       ((function.type=='mask') and (function.name=="appMenu")) start:         _page.append("""<!-- Application Menu -->""")         _page.append("""<div >""")         _page.append("""<a href=\"""")         _page.append(str(request.base + '/index'))         _page.append("""\">Index</a> | """)       ((function.type=='mask') and (function.name=="appMenu")) end:         _page.append("""</div><!-- End Application Menu -->""")   mask:     def appMenu(self) hidden:         #If you want something more than "Index" on the application menu bar         #then you should override this method in your CherryClass         #Normally the appMenu mask that you add will just be a list of links         #The code below will be added to your method by the aspect         <!-- Application Menu -->         <div>         <a py-attr="request.base + '/index'" href="">Index</a>         </div>         <!-- End Application Menu -->     CherryClass Root(PageLayout): mask:     def appMenu(self) hidden:         <a href="menu">Menu</a> | <a href="help">Help</a>       def index(self):             Welcome to the Intranet Applications Page!<br><br>

Here's how it works:

  1. The user calls http://localhost/
  2. Root.Index() is called. Since it is a mask and is not hidden, this triggers the first start/end aspect section in PageLayout which adds a header
  3. Next, the start part of this aspect section makes a call to appMenu(), which triggers the second aspect section and adds a div section that includes a first link (index)
  4. Since we overriden appMenu() in Root, this is the version that is called instead of PageLayout.appMenu. In our version, we add a couple more links (menu and help)
  5. We leave appMenu(), so the relevant aspect part is called in PageLayout, which happens to closed the <div> section that contains the three links
  6. Next, we go back to index, running the instructions it actually contains, which happens to write "Welcome...." to the screen
  7. Finally, as we leave index(), the ad hoc aspect section in PageLayout adds a footer

In other words, if you wish to customize the navigation bar in each section of the site, you just need to derive the class from PageLayout, override its appMenu() routine, and add the relevant links. Brilliant :-)

Subdirectories

When accessing sub-directories, while web servers look for items in sub-directories on the filesystem, CherryPy just calls a routine in the form dir1_dir2_dir3.page(), where dir1_dir2_dir3 is an class derived from the CherryPy class (or, rather, since class declarations start with an uppercase letter and class instances start with a lowercase letter, the class is Dir1_dir2_dir3 while the instance is dir1_dir2_dir3), and page() is a routine located in this derived class.

When the URL only contains just the hostname with no appended reference to a sub-directory (ie. http://localhost/), CherryPy calls root.index() implicitely. In other cases, you must explicitely provide the name of the method you wish to call, ie. CherryPy will not implicitely call index if you type the URL http://localhost/sub/ : In this case, you must provide http://localhost/sub/index, which corresponds to sub.index().

Here's a sample which displays the familiar "Hello, world!" when calling http://localhost/, and displays a form when calling http://localhost/sub/index:

CherryClass Root: mask:         def index(self):                 <html><body>                         Hello, world !                 </body></html>   CherryClass Sub: mask:         def index(self, name="you"):                 <html><body>                         Hello, <b py-eval="name"></b> !                         <form py-attr="self.getPath()+'/index'" action="" method="get">                                 Enter your name: <input name=name type=text><br>                                 <input type=submit value=OK>                         </form>                         </body></html>

As explained above, you must use "/index" instead of just refering to the current "directory" sub/ because CherryPy will not call index implicitely unless you are located at the root level of the site.

Configuration

To modify the default settings that a CherryPy server uses, just create a configuration file in the same directory where the server lives, and name it after the source file. For instance, if the source file is hello/Hello.cpy, the resulting server is HelloServer.py; In this case, its configuration file is HelloServer.cfg. Use the -C switch to use a different configuration file, eg. "python HelloServer.py -C /dir1/dir2/myConfigFile.cfg".

Using a different port number

[server] socketPort=80

Some other options are available in the [server] section of the config file. Check out the "Deploying your website for production" chapter for more information about the different options.

Serving static contents

[staticContent] static=/home/remi/static data/images=/home/remi/images

Using this configuration, http://localhost/static/styleSheet.css tells the server to return  /home/remi/static/styleSheet.css, while http://localhost/data/images/girl.jpg servers  /home/remi/images/girl.jpg.

Note: Under Windows, use short filenames, eg. static=d:\Documents\CODESN~1\Python\cherry\hello\static

To let Apache serve static content: http://sourceforge.net/mailarchive/message.php?msg_id=4190130

Accessing custom sections from a configuration file

If the configuration file includes the following:

[user] name=Remi   [database] login=remiLogin password=remiPassword

those tuples can be access thus:

CherryClass Root:   view:     def index(self):         <html><body>             Hello, <py-eval="configFile.get('user','name')"><br>             to connect to the database, you should use:<br>             <py-eval="'Login:%s, Password:%s'%(configFile.get('database','login'), configFile.get('database','password'))">         </body></html>

Security

http://sourceforge.net/mailarchive/message.php?msg_id=4071518

CherryPy variables and functions

Variables

Request

This class instance contains all the informations about the request that was sent by the client.

  • request.headerMap: request.headerMap['user-agent']
  • request.cookieMap: (this information is also available through request.headerMap['cookie'])
  • request.base: Using "http://localhost:8000/dir/page?key1=value1&key2=value2", returns 'http://localhost:8000' (equivalent to 'http://'+request.headerMap['host'])
  • request.path: Using "http://localhost:8000/dir/page?key1=value1&key2=value2", returns 'dir/page'
  • request.paramMap: Using "http://localhost:8000/dir/page?key1=value1&key2=value2", returns {'key1': 'value1', 'key2': 'value2'}
  • request.originalPath: (See next item)
  • request.originalParamMap: Copies of request.path and request.paramMap, but unlike those, originalPath and originalParamMap cannot be modified
  • request.browserUrl: The URL as it appears in the browser window
  • request.method: Either GET or POST
  • request.rawHeader: Raw header as it was sent by the client
Response

Functions

In your code, you can define special functions that will change the server's behavior. To define these functions, just use Python's regular syntax and define them outside all CherryClasses. When you use different modules, you can define the same function in different modules. In this case, CherryPy will just concatenate the bodies of all functions, in the same order it reads the files.

initServer

Called by the server during initialization.

initRequest
initNonStaticRequest
initResponse
initNonStaticResponse

For those functions, see doc/tut/node16.html, section 14.2.2

onError

Deploying CherryPy

Low traffic

By default, CherryPy's web server cannot handle concurrent requests, but it can be configured to fork a new process to handle every incoming request or launch a fixed number of processes when started (not available under Windows), or create a new thread (available under Windows.) You can also consider load balancing.

Here are the relevant settings in the configuration file:

[server] #Those options are mutually exclusive...socketPort=80 socketFile=/tmp/mySocket.soc   #Either use forking or threading, but not both...forking=1 fixedNumberOfProcesses=10 threading=1   #To have an SSL server. See the relevant HowTo sslKeyFile sslCertificateFile   #To have an XML-RPC server. See the HowTo xmlRpc

High traffic

To deploy CherryPy behind another web server, there is a HowTo in the documentation that explains how to set this up. Says Rmi: "If you're concerned about the server crashing once in a while, you can set it up to run behind Apache via PersistentCGI and configure the PersistentCGI script to automatically restart the CherryPy server if it detects that is is not running anymore."

Standard Modules

Make sure the lib/ directory lives at the same level where the script lives, eg. c:\tmp\myscripts\sendmail.cpy and c:\tmp\lib. Do not name this script mail.cpy as it will create an error at compile time (infinite loop). Like the src/ directory, /lib is only needed to compile, but not to run a compiled server.

Mail

use Mail   CherryClass MyMail(Mail): function:     def __init__(self):         self.smtpServer='mail.acme.com'   CherryClass Root: mask:     def index(self):         <py-exec="myMail.sendMail('[email protected]', '[email protected]', '', 'text/plain', 'Hello', 'Hello,\nthis is me')">         <html><body>             Hi, I just sent an e-mail to [email protected]         </body></html>

HttpAuthenticate

The following takes advantage of the HttpAuthenticate and CookiAuthenticate classes so you just need to derive their getPasswordListForLogin() method to let those classes handle authentication:

use HttpAuthenticate   CherryClass Root(HttpAuthenticate): function:     def getPasswordListForLogin(login):         if login=='mySecretLogin': return ['mySecretPassword']         return []   mask:     def index(self):         <html><body>             Hello. I see you know the secret login and password ...         </body></html>       def unauthorized(self):         <html><body>             Hey dude, get out ! You're not allowed here if you don't know the login/password         </body></html>

CookieAuthenticate

doc/html/lib/node9.html

Forms

An exemple is provided in the demo that come's with CherryPy, and the CherryPy Library Reference has some documentation about this module.

MySQL

doc/html/lib/module-MySql.html . Note that you need to have the MySQLdb Python package installed.

Here's a sample that connects to the local MySQL server, uses the "mydb" database which contains the "clients" table which has two columns:

use MySql   CherryClass MyDb(MySql): function:     def __init__(self):         self.openConnection('localhost', 'root', '', 'mydb')   CherryClass Root: mask:     def index(self):         <html><body>             <table width=100% border=1>                 <tr>                         <th>Field1</th>                         <th>Field2</th>                 </tr>             <py-for="field1,field2 in myDb.query('select * from clients')">                                 <tr>                                         <td><py-eval="field1"></td>                                         <td><py-eval="field2"></td>                                 </tr>                         </py-for>                         </table>         </body></html>

Here's a sample to query a database, and display only one column through a mask section:

CherryClass Test: mask:         def index(self):                 <py-exec="table = myDb.query('select name from kids')">                 <!-- table is a two-dimension table, with rows and columns -->                 <py-for="row in table">                         <py-eval="row[0]"><br>                 </py-for>

MaskTools

doc/html/lib/module-MaskTools.html

Q&A

How come more than one process can be launched on TCP 8000?

By mistake, I let a running CherryPy server on 8000, compiled and ran a second one, with no error. How come?

What are hidden sections/class?

By design, functions are not callable through a URL, but you might also want to forbid users from calling other sections, or even an entire class directly: That's what the "hidden" keyword is used for.

Here's a sample that forbids the user from accessing the hidden mask through http://localhost/commonMasks/redLabel?label=test :

CherryClass CommonMasks: mask:     def redLabel(self, label) hidden:         <b><font color=red py-eval="label"></font></b>   CherryClass Root: mask:     def index(self):         <html><body>             Hello, <py-eval="commonMasks.redLabel('world')">         </body></html>

Here's an example to hide an entire class:

CherryClass CommonMasks hidden:

How to get the complete URL to the current class?

self.getPath(): by default, CherryPy creates a method called getPath for each CherryClass. This method returns the URL of the CherryClass.

In a form with multiple submit buttons, how to tell which one was pressed?

if kw.has_key('cmdChildCreate'):     myPage.append("<td>\nYou have select " + kw['cmdChildCreate'] + "\n</td>\n")

How to combine views and masks correctly?

Depending on which button the user clicked in a form, I need to display a different action script. Don't know what the best way to do this:

view:            def action(self, **kw):                 if kw.has_key("cmdCreate"):                         return kw["cmdCreate"]                 elif kw.has_key("cmdView"):                         res="<html><body>"                         res+="<td width=80% valign='top' align='left'>"                         res+="<table border=1>"                         etc....

Is there a way to call a mask from a view?

My code looks OK, but I get a syntax error

From the tutorial: "CherryPys policy is that one tab should be used to indent a block (its easier to hit once the TAB key rather than 4 times the SPACE key). However, we know that some people have some reasons not to use tabs (for instance, sending a program with tabs by email or posting it to a newsgroup doesnt work very well). Therefore, it is also possible to use whitespaces to indent blocks in CherryPys source files. By default, CherryPy will expect 4 whitespaces for one indentation. If you use something else (for instance, 3 whitespaces), then you have to use the -W 3 option to tell CherryPy about it. The way it works is very simple: when it reads a file, CherryPys preprocessor starts by replacing all occurences of 4 whitespaces (or 3, depending on the -W option) with one tab. Please note that, unlike Python, one tab can never correspond to 2 indentation levels. It always corresponds to one indentation level."

I'll add to this, that a syntax error in one section can have its cause lying elsewhere. For instance, a missing ) in the class below caused a syntax error in the aspect section in the Base class from which it was derived:

CherryClass Base abstract: aspect:         (function.type=='view') start:                 myPage=[]                 myPage.append(self.header())                 myPage.append(self.nav())           (function.type=='view') end:                 myPage.append(self.footer())                 return '' . join(myPage) CherryClass Root(Base): view:         def index(self):                 parents=[]                 for row in myDb.query('select * from parent'):                         for col in row:                                 parents.append(col)                 myPage.append(self.Create(parents)

Compiling this generates the following hard-to-find error:

File "clshServer.py", line 718     myPage.append(self.footer())          ^ SyntaxError: invalid syntax

I need to include more than one "use" line

use Form,MySql

What's AOP?

http://www.cherrypy.org/static/html/howto/node12.html

In Aspect, why does an excluded function still get handled?

In Base class, I have the following:

aspect:         (function.type=='view' and function.name!='index') start:

Still, Root.index gets to use Base's aspect stuff.

CherryPy generates .py files: Can customers see the source?

Is it an issue if the source files do not start with an uppercase letter?

The documentation for the py-code part says : "If you want to render some data inside the Python code, you must append it to the _page variable". Why the need for _ ?

<html><body>     Integers from 0 to 9:     <div py-code="         for i in range(10):             _page.append("%s "%i)     "></div> </body></html>

Why masks and versions?

Masks let you just copy/paste HTML, with or without any embedded CHTL/CGTL code, while versions require you to put the HTML code into a variable, eg.

page = "<html>" page+= "</html>"

As we saw in section 2.3, CherryPy source files are made of class and method declarations. So how to include templates in these source files? The solution I chose was to add another keyword before method definitions to specify whether what's coming up is a regular python method or a method using a templating language. The former methods are called views;  the latter ones are called masks.

So what's the difference between a function and a view if both are written using regular python? The difference is that views correspond to a URL and should return a python string containing some rendered data pulled from the file the URL links to. Functions are not directly accessible with a URL and they can return anything they want. Let's look for instance at the following actual CherryPy code, which shows all three of its special structures within a CherryClass.

Should index be located in mask or version?

Why initRequest/initNonStaticRequest, initResponse/initNonStaticResponse?

No way to have a single function to handle request/response?

Is there a way to implement acquisition la Zope?

If CherryPy does not provide Zope-like acquisition, how can we share objects between pages that are located in deeper sub-directories (eg. navigation bar, etc.)?

You can just derive your CherryClasses like you would derive a normal class in python ... Ie. if you want to share common stuff with methods in other classes, just derive their class from the Root class where this common stuff will be defined.

Any way to have CherryPy call Root.index if other classes don't implement it?

Just derive those classes from Root

Any way to have CherryPy call Myclass.index when calling http://localhost/myclass/ ?

Supposed to be available in release 0.9. In the mean time, you can use this:

 def initNonStaticRequest():      if request.path in ('studio','writing','resume', ...):         request.path+='/index'

Any way to use index.html instead of just index?

guess not : The default object in Zope is index_html

What features will CherryObjects offer?

http://cherrypy.org/myForum/viewThread?threadId=15

A mask includes links to other objects but CherryPy can't find them

In the following snippet, theme.css lives in the same directory where the generated server lives, but CherryPy can't find it (no error, the file is just ignored):

CherryClass Root: mask:         def index(self):                 <html>                 <head>                 <link rel="stylesheet" type='text/css' href="theme.css"/>                 <title>CLSH</title>

Path to static stuff must be set in the configuration file.

CherryPy vs. Zope?

http://sourceforge.net/mailarchive/forum.php?thread_id=1990353&forum_id=9986

CherryPy vs. Quixote?

http://sourceforge.net/mailarchive/message.php?msg_id=5506255

The mailing list archives over at SourceForge are displayed as one big HTML document

In the main page, select Threaded instead of the default Nested.

Resources

www.fredshack.com

Настройка CherryPy Environment

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

  • Использование тарбола
  • Использование easy_install
  • Использование Subversion

Требования

Основные требования к установке каркаса CherryPy включают в себя -

  • Python с версии 2.4 или выше
  • CherryPy 3.0

Установка модуля Python считается легким процессом. Установка включает в себя использование следующих команд.

python setup.py build python setup.py install

Пакеты Python хранятся в следующих каталогах по умолчанию -

/usr/local/lib/python2.4/site-packages or /usr/lib/python2.4/site-packages C:\Python or C:\Python2x Python:Lib:site-package

Установка с использованием тарболл

Тарбола представляет собой сжатый архив файлов или директории. Структура CherryPy обеспечивает тарбола для каждого из своих выпусков (альфа, бета и стабильные).

Она содержит полный исходный код библиотеки. Название происходит от утилиты, используемой в UNIX и других операционных систем.

Вот шаги, которые необходимо соблюдать при установке CherryPy с использованием смолы мяч -

Шаг 1 - Загрузить версию в соответствии с требованиями пользователя из http://download.cherrypy.org/

Шаг 2 - Поиск по каталогу , в котором тарболл была загружена и распаковывать его.Для операционной системы Linux, введите следующую команду -

tar zxvf cherrypy-x.y.z.tgz

Для Microsoft Windows, пользователь может использовать утилиты, такие как 7-Zip или Winzip для распаковки архива с помощью графического интерфейса.

Шаг 3 - Переместить вновь созданный каталог и использовать следующую команду для создания CherryPy -

python setup.py build

Для глобальной установки следующую команду следует использовать -

python setup.py install

Установка с помощью easy_install

Python Enterprise Application Kit (PEAK) обеспечивает модуль питона с именем Easy Install. Это облегчает развертывание пакетов Python. Этот модуль упрощает процедуру загрузки, создания и применения приложений и продуктов Python.

Легкая установка Необходимо установить в системе перед установкой CherryPy.

Шаг 1 - Загрузить модуль ez_setup.py из http://peak.telecommunity.com и запустить его с помощью права администратора на компьютере: Python ez_setup.py.

Шаг 2 - Следующая команда используется для установки Easy Install.

easy_install product_name

Шаг 3 - easy_install будет искать Python индекса пакетов (PyPI) , чтобы найти данный продукт.PyPI представляет собой централизованное хранилище информации для всех продуктов Python.

Используйте следующую команду для развертывания последнюю доступную версию CherryPy -

easy_install cherrypy

Шаг 4 - easy_install скачает CherryPy, построить и установить его на глобальном уровне в среде Python.

Установка с помощью Subversion

Установка CherryPy с использованием Subversion рекомендуется в следующих ситуациях -

  • Функция существует или ошибка была исправлена ​​и доступна только в коде на стадии разработки.

  • Когда разработчик работает над самой CherryPy.

  • Когда пользователь нуждается в ветвь от основной ветви в репозитории управления версиями.

  • Для исправления ошибок предыдущего релиза.

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

Выполните следующие действия, чтобы понять установку CherryPy с помощью Subversion-

Шаг 1 - Чтобы использовать самую последнюю версию проекта, необходимо проверить папку магистральный найденный в хранилище Subversion.

Шаг 2 - Введите следующую команду из оболочечной

svn co http://svn.cherrypy.org/trunk cherrypy

Шаг 3 - Теперь создайте каталог CherryPy и загрузить полный исходный код в него.

Проверка установки

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

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

import cherrypy cherrypy.__version__ '3.0.0'

Если CherryPy не установлен глобально среде Python локальной системы, то вам необходимо установить переменную окружения PYTHONPATH, иначе он будет отображать ошибку следующим образом -

import cherrypy Traceback (most recent call last): File "<stdin>", line 1, in ? ImportError: No module named cherrypy

www.w3ii.com


Смотрите также