Дәріс: Web-қосымшаларын әзірлеу
Web-қосымшалары арқылы HTML және XML құжаттарының басқаруындағы стандартты www-браузерімен жұмыс істейтін негізгі пайдаланушы интерфейсінің бағдарламасын түсінуге болады. Қолданушы интерфейсінің сапасын жақсарту үшін көбіне JavaScript қолданылады, алайда бұл интерфейс әмбебаптылығын бірнеше төмендетеді. Ескере кететіні интерфейсті java немесе Flash-апплеттерінде құруға болады, алайда бұндай қосымшаларды web-қосымшалары деп атау қиындық тудырады, өйткені, сервермен байланысу үшін java немесе Flash өздерінің хаттамаларын қолдана алады, яғни HTTP хаттамасы WWW үшін стандартты емес байланыс қолданылады.
Web-қосымшаларын құру кезінде Пішінін (сыртқы түрін,стилін), Мазмұнын және Деректерді өңдеу логикасын бөлуге тырысады. Web-сайттарды құрудың заманауи технологиялары бұл идеалға жеткілікті түрде жетуге мүмкіндік береді. Дегенмен, тіпті көп деңгейлі қосымшаларды қолданбай-ақ басқа екеуін тиіспейтін (немесе жуық тимей(не затрагивая)), бұлардың кез келген аспектін өзгертуге мүмкіндік беретін стилін ұстануға болады. Бұл тақырыптың жалғасын бағдарламалау ортасына арналған бөлімде танысуға болады.
CGI-сценарилер
WWW үшін қосымшаларды құрудың классикалық жолы – CGI-сценарилерін жазу болып табылады (кейде – скриптер деп те аталады). CGI (Common Gateway Interface, жалпы шлюзді интерфейс) – бұл сыртқы қосымшалармен сервердің өзара әрекеттесуін реттейтін стандарт. WWW жағдайда, веб-сервер нақты сценариге генерациялық бетті жасау үшін сұрау жіберуі мүмкін. Бұл сценарий веб-серверден мәліметтердің кірісін алып (ол өз кезегінде оны қолданушыдан алуы мүмкін), дайын обьектіні жинақтайды (сурет, аудио мәліметтер, стилдер кестелері және тағы басқа)
Сценарийді шақырған кезде веб-сервер стандартты енгізу арқылы оған ақпаратты тасымалдайды, айнымалылар ортасы және, ISINDEX үшін пәрмен жолы аргументтері арқылы (олар sys.argv арқылы қол жетімді.).
Толтырылған браузердегі веб-сервер формасының (және CGI-сценарий) екі негізгі мәліметтерді жіберудің әдістері – GET және POST. Әдіске байланысты мәліметтер әр түрлі жіберіледі. Бірінші жағдайда олар тікелей URL-ге кодталады және орналастырылады, мысалы http://host/cgibin/a.cgi?a=1&b=3. Сценарий оларды QUERY_STRING айнымалы ортасының атымен алады. POST әдісі жағдайында олар стандартты енгізуге жіберіледі.
Сценарийлер дұрыс жұмыс істеуі үшін осы каталог үшін арналған веб-серверде (әдетте ол cgi-bin деп аталады) немесе, егер бұл сервер конфигурациясымен рұқсат етілген болса, HTML құжатының кез келген жерінде орналасады. Сценарийдің орындалатын белгісі болуы тиіс. Unix жүйесінде оны chmod a+x командасы арқылы орнатуға болады.
Келесі қарапайым сценарий os.environ сөздігінен мәнін шығарады және оған не жіберілгенін көруге мүмкіндік береді.
#!/usr/bin/python
import os
print """Content-Type: text/plain
%s""" % os.environ
Оның көмегімен веб-сервермен орнатылған айнымалылар ортасын көруге болады. web-серверге CGI-сценарий берілген файл тақырыпша бөлімін қамтиды, мұнда мета-ақпаратпен берілген өріс көрсетілген (мазмұн түрі, құжаттың соңғы жаңартылған уақыты, кодтау және т.б.).
Негізгі айнымалылар ортасы сценарийлер жасау үшін жеткілікті:
QUERY_STRING
Сұрау жолы.
REMOTE_ADDR
Клиент IP-адресі.
REMOTE_USER
Клиент аты (егер ол табылған болса).
SCRIPT_NAME
Сценарий аты.
SCRIPT_FILENAME
Сценариймен берілген файл аты.
SERVER_NAME
Сервер аты.
HTTP_USER_AGENT
Браузер клиентінің атауы.
REQUEST_URI
(URI) жолдар сұрауы.
HTTP_USER_AGENT
Сервер аты.
HTTP_ACCEPT_LANGUAGE
Қажетті құжат тілі.
CGI-сценарийіндегі os.environ сөздігі қамтиды:
{
'DOCUMENT_ROOT': '/var/www/html',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'GATEWAY_INTERFACE': 'CGI/1.1',
'HTTP_ACCEPT_LANGUAGE': 'en-us, en;q=0.50',
'REMOTE_ADDR': '127.0.0.1',
'SERVER_NAME': 'rnd.onego.ru',
'HTTP_CONNECTION': 'close',
'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; U; Linux i586; en-US;
rv:1.0.1) Gecko/20021003',
'HTTP_ACCEPT_CHARSET': 'ISO-8859-1, utf-8;q=0.66, *;q=0.66',
'HTTP_ACCEPT': 'text/xml,application/xml,application/xhtml+xml,
text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,
image/gif;q=0.2,text/css,*/*;q=0.1',
'REQUEST_URI': '/cgi-bin/test.py?a=1',
'PATH': '/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin',
'QUERY_STRING': 'a=1&b=2',
'SCRIPT_FILENAME': '/var/www/cgi-bin/test.py',
'HTTP_KEEP_ALIVE': '300',
'HTTP_HOST': 'localhost',
'REQUEST_METHOD': 'GET',
'SERVER_SIGNATURE': 'Apache/1.3.23 Server at rnd.onego.ru Port 80',
'SCRIPT_NAME': '/cgi-bin/test.py',
'SERVER_ADMIN': 'root@localhost',
'SERVER_SOFTWARE': 'Apache/1.3.23 (Unix) (Red-Hat/Linux)
mod_python/2.7.8 Python/1.5.2 PHP/4.1.2',
'SERVER_PROTOCOL': 'HTTP/1.0',
'REMOTE_PORT': '39251'
}
Келесі CGI-сценарийі қара шаршыны береді (суреттерді өңдеу үшін онда Image модулі қолданылады):
#!/usr/bin/python
import sys
print """Content-Type: image/jpeg
"""
import Image
i = Image.new("RGB", (10,10))
i.im.draw_rectangle((0,0,10,10), 1)
i.save(sys.stdout, "jpeg")
Cgi модулі
Python-да cgi модулі түріндегі CGI қолдауы бар. Келесі мысал оның кейбір мүмкіндіктерін көрсетеді:
#!/usr/bin/python
# -*- coding: cp1251 -*-
import cgi, os
# сұрауды талдау
f = cgi.FieldStorage()
if f.has_key("a"):
a = f["a"].value
else:
a = "0"
# сұрауды өңдеу
b = str(int(a)+1)
mytext = open(os.environ["SCRIPT_FILENAME"]).read()
mytext_html = cgi.escape(mytext)
# жауапты қалыптастыру
print """Content-Type: text/html
<html><head><title>Мысалдың шешімі: %(b)s = %(a)s + 1</title></head>
<body>
%(b)s
<table width="80%%"><tr><td>
<form action="me.cgi" method="GET">
<input type="text" name="a" value="0" size="6">
<input type="submit" name="b" value="Өңдеу">
</form></td></tr></table>
<pre>
%(mytext_html)s
</pre>
</body></html>""" % vars()
Бұл мысалда берілген сандар формасына 1 қосылады. Сонымен қатар өз сценарийінің бастапқы коды шығарылады. Атап өту қажет, >, <, & символдарын экрандау үшін cgi.escape() функиясы қолданылған. Веб-беттерді қалыптастыру үшін пішімдеу операциясы қолданылған. Сөздік ретінде ауыстыруды орындау үшін, барлық жергілікті айнымалыларымен берілген vars() сөздігі қолданылған. Олар пішімдеу командасымен түсіндірілмес үшін, пайыз белгілерін екі еселеуге тура келді. Мән қолданушыдан қалай алынғанына назар аудару қажет. FieldStorage обьектісі сөздікке жуық, сол ерекшелікпен, әдеттегі мәнді алу үшін value атрибутын қосымша қарап шығу керек. Іс мәнісінде, сценарийге тек мәтіндік мәндер ғана емес, сонымен қатар файлдарда жібіріле алады, сондай-ақ бір және сол атпен берілген көптеген мәндерде.
Абайлаңыз!
CGI-сценарийінің кіріс мәндерін өңдеу кезінде мұқият болу керек және рұқсат етілген мәндерді мұқият тексеру керек. Клиент кіруге не болсада жібере алады деп санау керек. Осылардың ішінен таңдау керек және сценарий күтіп отырғанды ғана тексеру керек. Мысалы, қолданушыдан алынған мәліметтерді, файл жолына eval() функциясының аргументтері және оған ұқсас; командалық жолдың параметрлерін; деректер қорына SQL-сұрауларының бөліктері ретінде қоюдың қажеті жоқ. Сондай-ақ, алынған мәліметтерді тікелей қалыптастырылатын беттерге қоюдың қажеті жоқ, егер осы беттер URL-тапсырыс беруші клиенттерді ғана емес көретін болса, тіпті осы мәліметтің жалғыз оқырманы-сайт администраторы болған жағдайда да.
Жоғарыда келтірілген мысалда қабылдауға тексеру int() функциясын шақыру кезінде жүзеге асты: егер сандық емес мән берілген болса, сценарий апатты түрде аяқталушы еді, ал қолданушы Internal Server Error көрер еді.
Кіріс мәліметтерін талдаудан кейін олардың өңдеу фазаларын белгілеуге болады. CGI-сценарийінің бұл бөлігінде одан әрі шығару үшін айнымалылар есептеледі. Бұнда жіберілген айнымалылардың мәнін ғана емес, сондай-ақ олардың болуы немесе болмауы қақ екенін ескеру қажет, өйткені бұлда сценарий логикасына әсер етуі мүмкін.
Әйтеуір, дайын обьектінің (мәтіннің, HTML-құжатының, суреттің, обьект-мультимедиасының және т.б.) шығару фазасы. Оңайы, беттер шаблонын алдын ала дайындап қою (немесе оның ірі бөліктерін), содан соң айнымалылар мазмұнымен толтыру оңай.
Келтірілген мысалда аттар сұрау жолында тек бір рет шығып тұрды. Кейбір формалар бір ат үшін бірнеше мәндерді тудырады. Барлық мәндерді getlist() әдісі көмегімен алуға болады.
lst = form.getlist("fld")
lst тізімі веб-формасынан алынған fld атымен берілген қанша өріс болса, сонша мәндерді қамтитын болады (ол бос болуыда мүмкін, егер ешбір өріс берілген атпен толтырылмаса).
Кейбір жағдайларда серверге файлдарды жіберу қажет (upload-істеу). Келесі мысал және оған келтірілген пікер бұл тапсырмамен түсінуге көмектеседі.
#!/usr/bin/env python
import cgi
form = cgi.FieldStorage()
file_contents = ""
if form.has_key("filename"):
fileitem = form["filename"]
if fileitem.file:
file_contents = """<P>Содержимое переданного файла:
<PRE>%s</PRE>""" % fileitem.file.read()
print """Content-Type: text/html
<HTML><HEAD><TITLE>Загрузка файла</TITLE></HEAD>
<BODY><H1>Загрузка файла</H1>
<P><FORM ENCTYPE="multipart/form-data"
ACTION="getfile.cgi" METHOD="POST">
<br>Файл: <INPUT TYPE="file" NAME="filename">
<br><INPUT TYPE="submit" NAME="button" VALUE="Передать файл">
</FORM>
%s
</BODY></HTML>""" % file_contents
Басында сценарийдің соңында келтірілген веб-форманы қарастыру керек: дәл сол CGI-сценарийі бойынша үнделген қолданушыға шығарылады. Форма веб-браузерде "Browse" түймесімен жолақты жазумен ұсынылатын, file түр өрісіне ие. "Browse" түймесін баса отыра қолданушы, қолданушының компьтерінде ОЖ-де қолжетімді, файлды таңдайды. Содан кейін, файлдарды серверге жіберу үшін, ол “Файылды жіберу” түймесін баса алады.
CGI-сценарийінің жөндеу үшін cgitb модулін қолдануға болады. Қателіктер туындаған кезде бұл модуль қателік орнын көрсете отыра, қызарған HTML-бетін шығарады. Жөнге келген сценарийдің басына қою керек
import cgitb
cgitb.enable(1)
Немесе, егер браузерде қателіктерді көрсету керек емес болса:
import cgitb
cgitb.enable(0, logdir="/tmp")
Тек есте сақтайтыны, сценарий жөнге келтірілсе, бұл жолдарды алып тастау керек, өйткені ол сценарий кодының бөліктерін шығарады. Бұл зиянкестермен, CGI-сценарийлерінің осал тұстарын тауып немесе құпия сөздерді көрумен , пайдаланылуы мүмкін.
CGI-дан кейін не?
Өкінішке орай, интерактивті құрылысы және CGI негізіндегі қатысқан сайттың өзінің шектеулері болады, негізінен өндірушімен байланысқан. Өйткені әр сұрау үшін шамамен бір сценарийді шақыру керек (ал ол дегеніміз - Python интерпретаторын жіберу) одан, мүмкін, деректер қорымен байланыс орнатуын істеу және т.б. Python интерпретаторының жіберу уақыты онша ірі емес, соған қарамастан бос емес серверде ол процессордың жүктемесіне үлкен әсер беруі мүмкін.
Интерпретатор жедел жадыда орналасқан, және деректер қорымен байланыс қолжетімділігі болуы керек.
Мұндай технологиялар бар және әдетте, веб-сервер-де құрамалы, модулдерге сүйенеді.
CGI жұмысын жеделжету үшін әртүрлі сызбалар қолданылады, мысалы FastCGI немесе PCGI (Persistent CGI). Осы дәрісте mod_python деп аталатын Apache web-сервері үшін арнайы модул қарастырылады.
Модуль құжаттамада берілген нұсқаулықтарға сәйкес, веб-серверде орнатылған болсын.
mod_python модулі сценарий-өңдіргішіне Apache серверімен HTTP-сұрауының кез келген сатысында өңдеу үдерісне кірістіруге мүмкіндік береді, сценарий қандайда бір жолмен функция аты болуы тиіс.
Ең алдымен, сценарий-өңдеуші жұмыс істейтін каталогты белгілеп алу керек. Бұл каталог /var/www/html/mywebdir болсын. Веб-сервер, бұл каталогте mod_python пайдалану керек екенін білу үшін, Apache файл конфигурациясына келесі жолды енгізу керек:
<Directory "/var/www/html/mywebdir>
AddHandler python-program .py
PythonHandler mprocess
</Directory>
Осыдан кейін веб-серверді қайта жіберу қажет, егер бәрі қатесіз шықса, mprocess.py өңдегішін жаза бастауға болады. Бұл сценарий кез келген http://localhost/*.py түріндегі сұрауларға жауап береді.
Келесі mprocess.py сценарийі браузер бетіне Hello, world! Сөзін шығарады:
from mod_python import apache
def handler(req):
req.content_type = "text/html"
req.send_http_header()
req.write("""<HTML><HEAD><TITLE>Hello, world!</TITLE></HEAD>
<BODY>Hello, world!</BODY></HTML>""")
return apache.OK
CGI-сценарийінен сценарий – өңдеушінің айырмашылығы:
1. Сценарий – өңдеуші әр HTTP-сұрауында іске қосылмайды: ол жадыда орналасқан, және одан керекті функция-өңдеушілері шақырылады (келтірілген мысалда бұндай функция жалғыз- handler()). Әр веб-сервердің үдеріс-тұқымы (процесс-потомок) өзінің сценарий көшірмесіне және Python интерпретаторына ие.
2. Соның нәтижесінде п.1 әртүрлі HTTP-сұраулары біодей жаһандық айнымалыларды бөледі. Мысалы, осылайша деректер қорымен байланыстарды баптауға және оны барлық сұрауларда қолдануға болады.
3. Өңдеуші ру кеңейтілуімен берілген кез келген файл кезінде іске қосылады, ал CGI-сценарийі әдетте нақты атау кезінде іске қосылады.
4. Өңдіруші сценарийлерді бірдей каталогте орналасқан модулдерді көреді деп есептеуге болмайды. sys.path-ке кейбір каталогтарды енгізу қажет болуы мүмкін.
5. Ағымдағы жұмыс каталогіде ( оны os.getcwd() функциясы көмегімен білуге болады ) өңдірушімен бірдей каталогте орналаспаған.
6. #!-жолы сценарийдің бірінші жолында Python интерпретаторының нұсқасын анықтамайды. mod_python-ге құрастырылған нұсқасы жұмыс істейді.
7. Барлық қажетті параметрлер Request-объект түріндегі өңдірушіге жіберіледі. Қайтарылатын мәндерде осы обьект арқылы жіберіледі.
8. Веб-сервер өңдеуші сценарийдің өзгергенін байқайды, бірақ оған импортталатын модульдердегі өзгерісті байқамай да. touch mprocess.py командасы сценарий файылының өзгерген күнін жаңартады.
9. os.environ көрінісі өңдірушіде қиылған болуы мүмкін. Сонымен қатар, өңдеуші сценарийіндегі шақырылған басқа бағдарламалар оны мұраланбайды. Айнымалыларды басқа жолмен алуға болады: req.add_common_vars(); params = req.subprocess_env.
10. Өңдіруші сценарийі “бір рет пайдаланатын” болып табылмағандықтан, CGI-сценарийі сияқты, бағдарлама қателігі кезінде жадының азаюы (бағдарлама керек емес жадыны босатпайды) болуы мүмкін. MaxRequestsPerChild параметірінің (бір үдеріс-тұқымымен өңделген, сұраудың максималды санын) мәнін нөлден артық орнату қажет.
Тағы бір мүмкін өңдіргіш сценарийнің идентификациясы:
def authenhandler(req):
password = req.get_basic_auth_pw()
user = req.connection.user
if user == "user1" and password == "secret":
return apache.OK
else:
return apache.HTTP_UNAUTHORIZED
Бұл функцияны ,алдында қарастырылған, mprocess.py модуліне қосу керек. Сонымен қатар, идентификация сұрауы (PythonAuthenHandler) үшін өңдірушіні тағайындай отыра, конфигурацияны толықтыру қажет, сондай-ақ, әдеттегі Apache үшін AuthType,AuthName, require директивалары, авторизация тәсілін анықтайтын:
<Directory "/var/www/html/mywebdir>
AddHandler python-program .py
PythonHandler mprocess
PythonAuthenHandler mprocess
AuthType Basic
AuthName "My page"
require valid-user
</Directory>
Әрине, бұл тек мысал ғана. Шын мәнінде идентификация қиынырақ берілуі мүмкін.
Басқа мүмкін құрастырулар (к mod_python-қа құжаттама бойынша, қандай өңдеуші сұраныстарда шақырылатынын білуге болады):
PythonPostReadRequestHandler
Алынған сұраныстың оның алынғаннан кейінгі өңделуі.
PythonTransHandler
URI сұранысын өзгертуге мүмкіндік береді (соның ішінде виртуальды желінің атын).
PythonHeaderParserHandler
Сұраулар өрісін өңдеу.
PythonAccessHandler
Шектелген қолжетілімдікті өңдеу (мысалы, IP-адрестері бойынша).
PythonAuthenHandler
Қолданушы идентификациясы.
PythonTypeHandler
Құжат түрінің, тілдің және т.б. анықталуы және/немесе настройкасы.
PythonFixupHandler
Өңдегіші мазмұнын шақырар алдында тікелей өрістерді өзгерту.
PythonHandler
Сұрау өндіргішінің негізінде.
PythonInitHandler
PythonPostReadRequestHandler немесе PythonHeaderParserHandler байланысты веб-сервер конфигурациясын табу.
PythonLogHandler
Журналындағы жазуды басқару.
PythonCleanupHandler
Request-объектісін жою алдында тікелей шақырылатын өңдеуші.
Кейбір осы өңдірушілер тек жаһанды түрде жұмыс істейді, себебі шақырылу кезінде олардың қосымша каталогіде белгісіз болуы мүмкін ( мынадай, мысалы PythonPostReadRequestHandler).
mod_python көмегімен динамикалық мазмұнмен берілген веб-сайттарды құруға болады және Python-сценарии арқылы кейбір веб-серверлердің жұмыс істеу аспектісін бақылауға болады.
Ндіруші ортасы
Статикалық құжаттамалармен және CGI-сценарийлері орналасқан веб-серверге қарағанда, Ввб-қосымшаларын құру үшін одан да күрделі тәсілдер қолданылады. Тағайындалуына байланысты мұндай бағдарламалық жүйелер веб-қосымшалардың сервері, мазмұнды басқару жүйесі (CMS, Content Management System), веб-жарияланым және WWW-порталдарын құру үшін арналған тәсілдер жүйесі деп аталады. Сонымен қатар CMS-жүйесі веб-қосымшасы сияқты орындалуы мүмкін, ал порталдарды құру үшін арналған тәсілдер, CMS – жүйесі ішкі жүйе болып табылатын, веб-жарияланым жүйесіне негізделуі мүмкін. Сондықтан нақты қажеттіліктер үшін жүйені таңдау кезінде, ол қандай функцияны орындайтынын нақтылап алу қажет.
Pyton тілі жеткілікті түрде бірнеше танымал қосымшаларына ие. Веб-қосымшаларының серверін құру үшін ең танымалы Zope болып табылады (см.
http://zope.org) (Z Object Publishing Environment, обьектілерді жариялау ортасы среда). Zope кірістірілген веб-серверіне ие, бірақ басқа веб-серверменде жұмыс істей алады, мысалы, Apache. Zope негізінде веб-порталын құруға болады, мысалы, Plone/Zope көмегі арқылы, бірақ өзіңіздің веб-қосымшаларыңызды дамытуға болады. Сонымен қатар Zope форманы, мазмұнын, логикасын бөлуге мүмкіндік береді, яғни мазмұнмен жеке адамдар (мазмұн бойынша менеджерлер), формамен-басқалары(веб-дизайнерлер), ал логикамен-үшіншілері (бағдарламаушылар). Zope жағдайында логиканы Python тілі көмегімен беруге болады, Форма графикалық немесе мамандандырылған веб-редакторларындар құрылуы мүмкін, ал мазмұнымен жұмыс Zope-тің өзінің веб-формасы арқылы орындалады.