Turbogears - คู่มือฉบับย่อ
Web Framework คืออะไร?
Web Application Framework หรือเพียงแค่ Web Framework แสดงถึงชุดของไลบรารีและโมดูลซึ่งช่วยให้นักพัฒนาเว็บแอปพลิเคชันสามารถเขียนแอปพลิเคชันได้โดยไม่ต้องกังวลเกี่ยวกับรายละเอียดระดับต่ำเช่นโปรโตคอลการจัดการเธรดเป็นต้น
TurboGears คืออะไร?
TurboGears เป็นเฟรมเวิร์กเว็บแอปพลิเคชันที่เขียนด้วยภาษา Python สร้างโดย Kevin Dangoor ในปี 2548 TurboGears เวอร์ชันล่าสุด (เวอร์ชัน 2.3.7) ได้รับการจัดการโดยกลุ่มนักพัฒนาที่นำโดย Mark Ramm และ Florent Aide
TurboGears เป็นไปตามกระบวนทัศน์ Model-View-Controller เช่นเดียวกับเว็บเฟรมเวิร์กที่ทันสมัยที่สุดเช่น Rails, Django, Struts เป็นต้น
Model View Controller
MVC เป็นรูปแบบการออกแบบซอฟต์แวร์สำหรับการพัฒนาเว็บแอปพลิเคชัน รูปแบบ Model View Controller ประกอบด้วยสามส่วน -
Model - ระดับต่ำสุดของรูปแบบมีหน้าที่ในการรักษาข้อมูล
View - มีหน้าที่ในการแสดงข้อมูลทั้งหมดหรือบางส่วนให้กับผู้ใช้
Controller - รหัสซอฟต์แวร์ที่ควบคุมการโต้ตอบระหว่าง Model และ View
MVC ได้รับความนิยมเนื่องจากแยกตรรกะของแอปพลิเคชันออกจากเลเยอร์อินเทอร์เฟซผู้ใช้และสนับสนุนการแยกข้อกังวล ที่นี่ Controller จะรับคำขอทั้งหมดสำหรับแอปพลิเคชันจากนั้นจะทำงานร่วมกับ Model เพื่อเตรียมข้อมูลที่จำเป็นสำหรับ View จากนั้น View จะใช้ข้อมูลที่เตรียมโดย Controller เพื่อสร้างคำตอบสุดท้ายที่สามารถนำเสนอได้ นามธรรม MVC สามารถแสดงเป็นกราฟิกได้ดังนี้ -
นางแบบ
Model มีหน้าที่จัดการข้อมูลของแอปพลิเคชัน ตอบสนองต่อคำขอจากมุมมองและยังตอบสนองต่อคำสั่งจากคอนโทรลเลอร์เพื่ออัปเดตตัวเอง
มุมมอง
การนำเสนอข้อมูลในรูปแบบเฉพาะที่เกิดจากการตัดสินใจของผู้ควบคุมในการนำเสนอข้อมูล เป็นระบบเทมเพลตตามสคริปต์ที่รวมเข้ากับเทคโนโลยี AJAX ได้ง่ายมาก
ตัวควบคุม
คอนโทรลเลอร์มีหน้าที่ตอบสนองต่ออินพุตของผู้ใช้และดำเนินการโต้ตอบกับอ็อบเจ็กต์โมเดลข้อมูล คอนโทรลเลอร์ได้รับอินพุตตรวจสอบความถูกต้องของอินพุตและดำเนินการทางธุรกิจที่ปรับเปลี่ยนสถานะของโมเดลข้อมูล
TurboGears สร้างขึ้นจากไลบรารีและเครื่องมือต่างๆ เครื่องมือเหล่านี้มีการเปลี่ยนแปลงระหว่าง TurboGears เวอร์ชันต่างๆ ส่วนประกอบของเวอร์ชันปัจจุบัน (เวอร์ชัน 2.3.7) แสดงอยู่ด้านล่าง
SQLAlchemy
เป็นชุด SQL โอเพ่นซอร์สที่จัดเตรียม Object Relation mapping (ORM) สำหรับโค้ด Python
เกนชิ
เครื่องมือสร้างเทมเพลตนี้ใช้เพื่อสร้างส่วนหน้าของแอปพลิเคชัน TG ระบบเทมเพลตของเว็บจะรวมเทมเพลตเข้ากับแหล่งข้อมูลเพื่อแสดงผลเว็บเพจแบบไดนามิก
ToscaWidgets
เป็นวิดเจ็ตไลบรารีสำหรับสร้างฟอร์ม HTML พร้อมตัวควบคุมฝั่งเซิร์ฟเวอร์ Tosca ยังทำหน้าที่เป็นมิดเดิลแวร์เพื่อเชื่อมต่อกับวิดเจ็ต JavaScript และชุดเครื่องมือ
กระปุกเกียร์
มีชุดคำสั่งสำหรับจัดการโครงการและแอปพลิเคชัน TurboGears ของเซิร์ฟเวอร์ แอปพลิเคชัน TurboGears สามารถปรับใช้บนเว็บเซิร์ฟเวอร์ที่รองรับ WSGI
Web Server Gateway Interface (WSGI) ถูกนำมาใช้เป็นมาตรฐานสำหรับการพัฒนาโปรแกรมประยุกต์บนเว็บ Python WSGI เป็นข้อกำหนดสำหรับอินเทอร์เฟซสากลระหว่างเว็บเซิร์ฟเวอร์และเว็บแอปพลิเคชัน แพคเกจ wsgiref เป็นการใช้งานอ้างอิงของ WSGI ใช้เพื่อเพิ่มการสนับสนุน WSGI ให้กับเว็บเฟรมเวิร์กเว็บ 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 shell
Python app.py
ป้อน http://localhost:8080 ในแถบที่อยู่ของเบราว์เซอร์เพื่อดูข้อความ 'Hello World TurboGears'
tg.devtoolsของ TurboGears ประกอบด้วย Gearbox เป็นชุดคำสั่งที่มีประโยชน์สำหรับการจัดการโครงการ TG ที่ซับซ้อนมากขึ้น สามารถสร้างโครงการสแต็กแบบเต็มได้อย่างรวดเร็วโดยคำสั่ง Gearbox ต่อไปนี้ -
gearbox quickstart HelloWorld
สิ่งนี้จะสร้างโครงการที่เรียกว่า HelloWorld.
โครงการ TurboGears มีไดเร็กทอรีต่อไปนี้ -
Config - การตั้งค่าโครงการและการกำหนดค่าอาศัยอยู่ที่ใด
Controllers - ตัวควบคุมโครงการทั้งหมดตรรกะของเว็บแอปพลิเคชัน
i018n - ไฟล์แปลสำหรับภาษาที่รองรับ
Lib - ฟังก์ชันและคลาสของยูทิลิตี้หลาม
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
หลังจากเริ่มเซิร์ฟเวอร์ผ่านคำสั่ง 'กระปุกเกียร์' 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__ ส่งไปยังเมธอด Controller ที่คำขอถูกส่งไป
เหตุการณ์แม้ว่าเนื้อหา HTML สามารถส่งคืนไปยังเบราว์เซอร์ได้ แต่สำหรับผลลัพธ์ขั้นสูงกว่านั้นขอแนะนำให้ใช้ template engine เสมอ ในโครงการสแต็กแบบเต็ม 'เริ่มต้นอย่างรวดเร็ว' โดยกระปุกเกียร์ Genshi ถูกเปิดใช้งานเป็นตัวแสดงเทมเพลตเริ่มต้น ในแอปพลิเคชั่นขั้นต่ำอย่างไรก็ตาม Genshi (หรือเครื่องมือเทมเพลตอื่น ๆ เช่น jinja) จำเป็นต้องติดตั้งและเปิดใช้งาน เครื่องมือเทมเพลต Genshi อนุญาตให้เขียนเทมเพลตใน xhtml บริสุทธิ์และตรวจสอบความถูกต้องเพื่อตรวจจับปัญหาในเวลาคอมไพล์และป้องกันไม่ให้แสดงเพจเสีย
เทมเพลตถูกอ้างถึงโดยใช้สัญกรณ์แบบจุด ในโปรเจ็กต์ Hello ของเรามีไดเร็กทอรีเทมเพลตเพื่อจัดเก็บเว็บเพจเทมเพลต ดังนั้นsample.html จะเรียกว่า hello.templates.sample(ไม่ได้กล่าวถึงนามสกุล) TurboGears แสดงเทมเพลตนี้ผ่านมัณฑนากรเปิดเผยเพื่อเชื่อมโยงวิธีการควบคุมกับมันโดยtg.render_template() ฟังก์ชัน
ฟังก์ชันตัวควบคุมที่เปิดเผยจะส่งคืนวัตถุพจนานุกรม Python อ็อบเจ็กต์พจนานุกรมนี้ถูกส่งต่อไปยังเทมเพลตที่เชื่อมโยง ตัวยึดตำแหน่งในเทมเพลตจะเต็มไปด้วยค่าพจนานุกรม
เริ่มต้นด้วยการให้เราแสดงหน้าเว็บด้วยสคริปต์ html ธรรมดา ตัวควบคุมที่เปิดเผยจะส่งกลับไฟล์null dictionary object เนื่องจากเราไม่ได้ตั้งใจที่จะส่งข้อมูลใด ๆ เพื่อแยกวิเคราะห์ภายในสคริปต์ HTML
วิธีสร้าง HTML ตัวอย่าง
ของเรา sample.htmlได้รับด้านล่าง ตรวจสอบให้แน่ใจว่าถูกเก็บไว้ในไดเร็กทอรี template ของโครงการ
<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 Protocol เป็นรากฐานของการสื่อสารข้อมูลในเว็บทั่วโลก มีการกำหนดวิธีการดึงข้อมูลจาก URL ที่ระบุไว้ในโปรโตคอลนี้ ตารางต่อไปนี้สรุปวิธีการ http ต่างๆ -
ซีเนียร์ | วิธีการและคำอธิบาย 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’ คือชื่อของช่องป้อนข้อความในรูปแบบการเข้าสู่ระบบซึ่งใช้เป็นพารามิเตอร์ของฟังก์ชันล็อกอิน ()
@expose("hello.templates.sample")
def login(self, nm):
name = nm
return {'person':name}
ดังที่เห็นได้ข้อมูลที่ได้รับจากแบบฟอร์มการเข้าสู่ระบบจะถูกส่งไปยังเทมเพลต sample.html (ใช้ก่อนหน้านี้) แยกวิเคราะห์โดยไฟล์Genshi template engine เพื่อสร้างผลลัพธ์ต่อไปนี้ -
วิธีการโพสต์
เมื่อฟอร์ม HTML ใช้เมธอด POST เพื่อส่งข้อมูลไปยังแอ็ตทริบิวต์ URL in action ข้อมูลฟอร์มจะไม่ถูกเปิดเผยใน 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 เวอร์ชันก่อนหน้า Genshi และ Kid ได้รับแรงบันดาลใจจากภาษาแม่แบบที่รู้จักกันดีอื่น ๆ เช่นHSLT, TAL และ PHP.
เทมเพลต Genshi ประกอบด้วยคำสั่งการประมวลผล คำสั่งเหล่านี้เป็นองค์ประกอบและคุณลักษณะในเทมเพลต คำสั่ง Genshi ถูกกำหนดไว้ในเนมสเปซhttp://genshi.edgewall.org/. ดังนั้นจึงต้องมีการประกาศเนมสเปซนี้ในองค์ประกอบรากของเทมเพลต
<html xmlns = "http://www.w3.org/1999/xhtml"
xmlns:py = "http://genshi.edgewall.org/"
lang = "en">
...
</html>
การประกาศด้านบนหมายความว่าเนมสเปซเริ่มต้นถูกตั้งค่าเป็น XHTML และคำสั่ง Genshi มีคำนำหน้า "py"
คำสั่ง Genshi
คำสั่งหลายอย่างถูกกำหนดไว้ใน Genshi รายการต่อไปนี้แจกแจงคำสั่งของ 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
py: ถ้า
เนื้อหาขององค์ประกอบคำสั่งนี้จะแสดงผลก็ต่อเมื่อนิพจน์ใน 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: เลือก
การประมวลผลตามเงื่อนไขขั้นสูงเป็นไปได้ด้วยการใช้ 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 ในโฟลเดอร์ template ได้รับข้อมูลพจนานุกรมและแยกวิเคราะห์ในเอาต์พุต 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: สำหรับคำสั่งซ้ำสำหรับแต่ละรายการในรายการที่ทำซ้ำได้โดยปกติจะเป็นวัตถุ Python List ถ้าitems = [1,2,3] มีอยู่ในบริบทเทมเพลตสามารถทำซ้ำได้โดยทำตาม py: for directive -
<ul>
<li py:for = "item in items">${item}</li>
</ul>
ผลลัพธ์ต่อไปนี้จะแสดงผล -
1
2
3
ตัวอย่างต่อไปนี้แสดงข้อมูลฟอร์ม HTML ที่แสดงผลในเทมเพลต total.html โดยใช้ py: สำหรับคำสั่งสามารถใช้ได้ดังนี้ -
<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 loop เพื่อแสดงเนื้อหาของวัตถุ 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
เรียกใช้ตัวควบคุมมาโคร () โดยป้อน URL ต่อไปนี้ในเบราว์เซอร์ -
http://localhost:8080/macro
ผลลัพธ์ต่อไปนี้จะแสดงผลในเบราว์เซอร์ -
py: กับ
คำสั่งนี้ช่วยให้คุณกำหนดนิพจน์ให้กับตัวแปรโลคัล ตัวแปรท้องถิ่นเหล่านี้ทำให้การแสดงออกภายใน verbose น้อยลงและมีประสิทธิภาพมากขึ้น
สมมติว่า x = 50 ให้ในข้อมูลบริบทสำหรับเทมเพลตต่อไปนี้จะเป็น py: with directive -
<div>
<span py:with = "y = 50; z = x+y">$x $y $z</span>
</div>
มันจะส่งผลต่อไปนี้ -
50 50 100
นอกจากนี้ยังมีเวอร์ชันอื่นสำหรับ py: พร้อมคำสั่ง -
<div>
<py:with = "y = 50; z = x+y">$x $y $z</py:with>
</div>
ในตัวอย่างต่อไปนี้ตัวควบคุม macro () จะส่งคืนอ็อบเจ็กต์ dict พร้อมคีย์ชื่อ 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 และคีย์คณิตศาสตร์โดยใช้ py: with directive
<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 namespace ในองค์ประกอบรากของเอกสาร HTML
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:xi = "http://www.w3.org/2001/XInclude >
คำประกาศข้างต้นระบุว่ามีคำสั่งประกอบด้วย ‘xi’คำนำหน้า ในการเพิ่มเนื้อหาของหน้า html อื่นในเอกสารปัจจุบันให้ใช้ xi: include directive ดังนี้ -
<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 มีการประกาศรวมเนมสเปซและเพิ่มเนื้อหาของ header.html และ footer.html นี่คือสคริปต์ HTML ของเทมเพลต \ include.html -
<html xmlns = "http://www.w3.org/1999/xhtml"
xmlns:xi = "http://www.w3.org/2001/XInclude">
<head>
<title>TurboGears Templating Example</title>
</head>
<body>
<xi:include href = "heading.html" />
<h2>main content </h2>
<xi:include href = "footer.html" />
</body>
</html>
นี่คือรหัส template \ Heading.html -
<html>
<head>
<title>TurboGears Templating Example</title>
</head>
<body>
<h1>This is page Header</h1>
</body>
</html>
ต่อไปนี้คือ template \ 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 directive ไม่พร้อมใช้งานข้อผิดพลาดจะเกิดขึ้น ในกรณีเช่นนี้ทรัพยากรทางเลือกอาจถูกโหลดโดยใช้ 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>
ก่อนเริ่มเซิร์ฟเวอร์ตรวจสอบให้แน่ใจว่าโฟลเดอร์แม่แบบมี head.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' ในเบราว์เซอร์ URL จะตอบสนองโดยแสดง -
{"hello": "World"}
jsonp การแสดงผล
jsonp ย่อมาจาก json พร้อมช่องว่างภายใน มันทำงานคล้ายกับเอาต์พุต json ยกเว้นข้อเท็จจริงที่ว่ามันให้การตอบสนองของแอ็พพลิเคชัน / จาวาสคริปต์พร้อมกับการเรียกใช้ฟังก์ชันจาวาสคริปต์โดยให้ค่าทั้งหมดที่คอนโทรลเลอร์ส่งคืนเป็นอาร์กิวเมนต์ของฟังก์ชัน
ในการเปิดใช้งานการเรนเดอร์ 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 สามารถสำรวจลำดับชั้นของวัตถุเพื่อค้นหาวิธีการที่เหมาะสมที่สามารถจัดการกับคำขอของคุณได้
โปรเจ็กต์ 'เริ่มต้นอย่างรวดเร็ว' พร้อมกระปุกเกียร์มีคลาส BaseController ในโฟลเดอร์ lib ของโปรเจ็กต์ มีให้ในชื่อ 'Hello / hello / lib / base.py' ทำหน้าที่เป็นคลาสพื้นฐานสำหรับคอนโทรลเลอร์ย่อยทั้งหมด ในการเพิ่มระดับย่อยของ URL ในแอปพลิเคชันให้ออกแบบคลาสย่อยที่เรียกว่า BlogController ที่มาจาก BaseController
BlogController นี้มีฟังก์ชั่นคอนโทรลเลอร์สองตัวคือ index () และ post () ทั้งสองแบบได้รับการออกแบบมาเพื่อแสดงแม่แบบแต่ละรายการคือ blog.html และ post.html
Note - เทมเพลตเหล่านี้ใส่ไว้ในโฟลเดอร์ย่อย - เทมเพลต / บล็อก
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
ประกอบด้วยคลาสฟอร์มซึ่งทำหน้าที่เป็นฐานสำหรับฟอร์มแบบกำหนดเอง มีคลาส TableForm ที่มีประโยชน์ในการแสดงผลฟิลด์ในตารางสองคอลัมน์ ListForm แสดงเขตข้อมูลในรายการที่ไม่เรียงลำดับ
ซีเนียร์ | ฟิลด์และคำอธิบาย |
---|---|
1 | TextField ช่องป้อนข้อความบรรทัดเดียว |
2 | TextArea ช่องป้อนข้อความหลายบรรทัด |
3 | CheckBox นำเสนอกล่องสี่เหลี่ยมที่ทำเครื่องหมายได้พร้อมฉลาก |
4 | CheckBoxList กล่องกาเครื่องหมาย pf กลุ่มที่เลือกได้หลายแบบ |
5 | RadioButton ปุ่มสลับเพื่อเลือก / ยกเลิกการเลือก |
6 | RadioButtonList กลุ่มของปุ่มวิทยุที่ใช้ร่วมกันโดยเฉพาะ |
7 | PasswordField คล้ายกับ Textfield แต่ไม่มีการเปิดเผยคีย์อินพุต |
8 | CalendarDatePicker ให้ผู้ใช้เลือกวันที่ |
9 | SubmitButton ปุ่มสำหรับส่งแบบฟอร์ม |
10 | ImageButton ปุ่มที่คลิกได้โดยมีรูปภาพอยู่ด้านบน |
11 | SingleSelectField เปิดใช้งานการเลือกรายการเดียวจากรายการ |
12 | MultipleSelectField เปิดใช้งานการเลือกหลายรายการจากรายการ |
13 | FileField ช่องสำหรับอัพโหลดไฟล์ |
14 | EmailField ช่องใส่อีเมล |
15 | URLField ช่องป้อนข้อมูลเพื่อป้อน URL |
16 | NumberField หมายเลข Spinbox |
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 คือ TextField ซึ่งสามารถรับได้เฉพาะตัวเลขเท่านั้น ลูกศรขึ้นและลงจะถูกสร้างขึ้นที่เส้นขอบด้านขวาเพื่อเพิ่มหรือลดจำนวนภายในนั้น ค่าเริ่มต้นยังสามารถระบุเป็นอาร์กิวเมนต์ในตัวสร้าง
twf.NumberField(value)
ทางด้านขวาของกล่อง CalendarDatePicker ปุ่มปฏิทินจะปรากฏขึ้น เมื่อกดตัวเลือกวันที่จะปรากฏขึ้น ผู้ใช้สามารถพิมพ์วันที่ในช่องด้วยตนเองหรือเลือกจากตัวเลือกวันที่
twd.CalendarDatePicker()
ออบเจ็กต์ EmailField แสดง TextField แต่ข้อความในนั้นต้องอยู่ในรูปแบบอีเมล
EmailID = twf.EmailField()
แบบฟอร์มต่อไปนี้ยังมี RadioButtonList คอนสตรัคเตอร์ของคลาสนี้มีอ็อบเจ็กต์ List เป็นค่าของพารามิเตอร์อ็อพชัน ปุ่มตัวเลือกสำหรับแต่ละตัวเลือกจะแสดงผล การเลือกดีฟอลต์ถูกระบุด้วยพารามิเตอร์ value
twf.RadioButtonList(options = ["option1","option2"],value = option1)
CheckBoxList จะแสดงกล่องกาเครื่องหมายสำหรับแต่ละตัวเลือกในรายการ
twf.CheckBoxList(options = [option1, option2, option3])
รายการแบบหล่นลงเรียกว่าเป็น SingleSelectfield ในไลบรารี ToscaWidgets นี้ รายการในวัตถุรายการที่สอดคล้องกับพารามิเตอร์ตัวเลือกในรูปแบบรายการแบบหล่นลง คำอธิบายภาพที่มองเห็นได้ถูกตั้งค่าเป็นค่าของพารามิเตอร์ 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 Forms Library เวอร์ชันก่อนหน้านี้เคยอาศัยโมดูล FormEncode สำหรับการสนับสนุนการตรวจสอบความถูกต้อง ToscaWidgets2 มีการสนับสนุนการตรวจสอบความถูกต้องในตัวในโมดูล tw2.core แล้ว อย่างไรก็ตามยังคงสามารถใช้เทคนิคการตรวจสอบความถูกต้องของ FormEncode ได้
ในการใช้แบบฟอร์ม ToscaWidgets ในการตรวจสอบความถูกต้องจะใช้ @validate มัณฑนากร
@validate(form, error_handler, validators)
’form’ คืออ็อบเจ็กต์ฟอร์ม ToscaWidgets ที่ต้องตรวจสอบ
‘error-handler’ เป็นวิธีการควบคุมที่ใช้ในการจัดการข้อผิดพลาดของฟอร์ม
‘validators’ เป็นอ็อบเจ็กต์พจนานุกรมที่มีตัวตรวจสอบ FormEncode
ประเภทของ Validator
โมดูล tw2.core มีคลาสตัวตรวจสอบความถูกต้องซึ่งตัวตรวจสอบความถูกต้องอื่น ๆ จะสืบทอดมา นอกจากนี้ยังสามารถออกแบบตัวตรวจสอบความถูกต้องที่กำหนดเองได้ ตัวตรวจสอบความถูกต้องที่สำคัญบางส่วนมีการอธิบายไว้ด้านล่าง -
LengthValidator- ตรวจสอบว่าค่ามีความยาวตามที่กำหนดหรือไม่ ขีด จำกัด ต่ำสุดและสูงสุดถูกกำหนดด้วยพารามิเตอร์ขั้นต่ำและสูงสุด ข้อความที่กำหนดเองสำหรับความยาวด้านล่างและด้านบนขั้นต่ำและสูงสุดสามารถระบุเป็นพารามิเตอร์ 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 จะมีตัวตรวจสอบความถูกต้องใด ๆ และทั้งหมดซึ่งเป็นคลาสย่อยของ CompoundValidator ที่ขยายได้
TurboGears มีระบบส่งข้อความที่สะดวกมากสำหรับการแจ้งข้อมูลไปยังผู้ใช้ในลักษณะที่ไม่เป็นการรบกวน คลาส TGFlash ในโมดูล tg ให้การสนับสนุนข้อความกระพริบที่เก็บไว้ในคุกกี้ธรรมดา คลาสนี้รองรับการดึงข้อความแฟลชจากฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ผ่าน JavaScript
render()เมธอดของคลาส TGFlash เมื่อใช้จาก Python เองสามารถเรียกใช้จากเทมเพลตเพื่อแสดงข้อความแฟลช หากใช้บน JavaScript จะมีอ็อบเจ็กต์ WebFlash มันเปิดเผยpayload() และ render() วิธีการดึงข้อความแฟลชปัจจุบันและแสดงผลจาก JavaScript
เมื่อโปรเจ็กต์ TurboGears ถูกสร้างขึ้นโดยใช้ 'การเริ่มต้นอย่างรวดเร็ว' จะมีเทมเพลต Master.html มันมีคำจำกัดความของตัวแปรของวัตถุแฟลชนั้น เนื้อหาของข้อความแฟลชนี้ที่ได้รับจากคอนโทรลเลอร์จะแทนที่ตัวยึดตำแหน่งที่ทำเครื่องหมายไว้ในเทมเพลตนี้
<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 จะถูกเก็บไว้ในคุกกี้ (ซึ่งโดยค่าเริ่มต้นคือ webflash) โดยใช้ tg.flash()วิธี. จากนั้นพารามิเตอร์ข้อความและสถานะจะถูกส่งไปยังข้อความนั้น
tg.flash('Message', 'status')
หากวิธีการที่เรียกว่าแฟลชทำการเปลี่ยนเส้นทางแฟลชจะมองเห็นได้ภายในหน้าที่เปลี่ยนเส้นทาง หากวิธีการนี้เปิดเผยเทมเพลตโดยตรงแฟลชจะมองเห็นได้ภายในเทมเพลตนั้นเอง
สามารถปรับแต่งลักษณะที่ปรากฏของข้อความแฟลชได้โดยใช้สไตล์ 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 สามารถทำได้โดยการตั้งค่าพารามิเตอร์สำหรับวิธีการกำหนดค่า () ของวัตถุ TGFlash หรือใน app_cfg.py (ในโฟลเดอร์ config) พารามิเตอร์ที่กำหนดได้คือ -
ซีเนียร์ | พารามิเตอร์และคำอธิบาย |
---|---|
1 | flash.cookie_name ชื่อคุกกี้ที่ใช้เก็บข้อความแฟลช ค่าเริ่มต้นคือ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 ซึ่งจะทำงานเมื่อแสดงแฟลชจาก JavaScript ค่าเริ่มต้นคือwebflash.render() |
6 | flash.js_template string.Template อินสแตนซ์ที่ใช้แทนการสนับสนุน JavaScript เต็มรูปแบบสำหรับข้อความแฟลช |
pop_payload() - ฟังก์ชั่น fetches current flash message, statusและข้อมูลที่เกี่ยวข้อง การรับข้อความแฟลชจะลบคุกกี้
render(container_id, use_js=True) - แสดงข้อความแฟลชภายในเทมเพลตหรือให้การสนับสนุน Javascript สำหรับพวกเขา
container_id คือ DIV ที่จะแสดงข้อความในขณะที่ use_js สลับระหว่างการแสดงผลแฟลชเป็น HTML หรือสำหรับการใช้งาน JavaScript
status - รับเฉพาะสถานะแฟลชปัจจุบันการรับสถานะแฟลชจะลบคุกกี้
message - รับเฉพาะข้อความแฟลชปัจจุบันการรับข้อความแฟลชจะลบคุกกี้
วิธีสร้างข้อความแฟลชง่ายๆ
ในตัวอย่างต่อไปนี้แฟลช () วิธีการถูกจัดเตรียมไว้ในคลาสตัวควบคุมรูท เรียกว่าข้อความ 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
มักจะต้องมีการเก็บข้อมูลการท่องเว็บอย่างง่ายที่แนบมากับเบราว์เซอร์ของผู้ใช้ เซสชันเป็นเทคนิคที่ใช้บ่อยที่สุด เซสชันแสดงถึงข้อมูลที่ไม่จำเป็นต้องจัดเก็บในรูปแบบถาวรเช่นไฟล์ดิสก์หรือฐานข้อมูล
อย่างไรก็ตาม sessiondata ใน TurboGears สามารถสำรองได้โดยระบบไฟล์ฐานข้อมูลหรือค่าคุกกี้ที่แฮช โดยทั่วไปข้อมูลเซสชันจำนวนเล็กน้อยจะถูกเก็บไว้ในคุกกี้ แต่สำหรับข้อมูลเซสชันจำนวนมากจะใช้ MemCache
MemCache เป็นดีมอนระดับระบบ ช่วยให้เข้าถึงข้อมูลแคชได้อย่างรวดเร็วและสามารถปรับขนาดได้อย่างมาก อย่างไรก็ตามมันมีไว้สำหรับใช้บนเซิร์ฟเวอร์ที่ปลอดภัยเท่านั้นดังนั้นจึงต้องได้รับการดูแลและรักษาความปลอดภัยโดย sysadmin
บีกเกอร์ในการจัดการเซสชัน
TurboGears ใช้ Beaker สำหรับการจัดการเซสชัน โปรเจ็กต์ที่เริ่มต้นอย่างรวดเร็วโดยกระปุกเกียร์จะถูกกำหนดค่าเริ่มต้นให้ใช้คุกกี้ที่แฮชเพื่อจัดเก็บข้อมูลเซสชัน
ทุกครั้งที่ลูกค้าเชื่อมต่อมิดเดิลแวร์เซสชัน (Beaker) จะตรวจสอบคุกกี้โดยใช้ชื่อคุกกี้ซึ่งได้กำหนดไว้ในไฟล์คอนฟิกูเรชัน หากไม่พบคุกกี้จะถูกตั้งค่าในเบราว์เซอร์ ในการเข้าชมครั้งต่อไปมิดเดิลแวร์จะค้นหาคุกกี้และใช้ประโยชน์จากคุกกี้
ในการเปิดใช้งานการจัดการเซสชันควรรวมคลาสเซสชันไว้ในโครงการโดยทำตามคำสั่งนำเข้า -
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)
คำอธิบายของพารามิเตอร์มีดังนี้ -
ซีเนียร์ | พารามิเตอร์และคำอธิบาย |
---|---|
1 | key ระบุพารามิเตอร์คอนโทรลเลอร์ที่ใช้ในการสร้างคีย์แคช |
2 | expire เวลาเป็นวินาทีก่อนที่แคชจะหมดอายุค่าเริ่มต้นคือ "ไม่เคย" |
3 | Type dbm หน่วยความจำไฟล์ memcached หรือไม่มี |
4 | cache_headers tuple ของชื่อส่วนหัวที่ระบุส่วนหัวการตอบกลับ |
5 | invalidate_on_startup หากเป็นจริงแคชจะไม่ถูกต้องทุกครั้งที่แอปพลิเคชันเริ่มทำงานหรือรีสตาร์ท |
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 เป็น Object Relation Mapper ที่มีประสิทธิภาพซึ่งช่วยให้นักพัฒนาแอปพลิเคชันได้รับพลังและความยืดหยุ่นอย่างเต็มที่ของ SQL นอกเหนือจากการรองรับฐานข้อมูลที่ใช้ SQL ผ่าน SQLAlchemy แล้ว TurboGears ยังรองรับฐานข้อมูล MongoDB แม้ว่า Ming ในส่วนนี้จะกล่าวถึงการทำงานของ SQLAlchemy
ORM (Object Relational Mapping) คืออะไร?
แพลตฟอร์มภาษาโปรแกรมส่วนใหญ่เน้นเชิงวัตถุ ข้อมูลในเซิร์ฟเวอร์ RDBMS ในทางกลับกันจะถูกจัดเก็บเป็นตาราง การแม็ปความสัมพันธ์ของวัตถุเป็นเทคนิคในการแม็ปพารามิเตอร์วัตถุกับโครงสร้างตาราง RDBMS ที่อยู่ภายใต้ ORM API มีเมธอดในการดำเนินการ CRUD โดยไม่ต้องเขียนคำสั่ง SQL ดิบ
เมื่อโปรเจ็กต์ TurboGears ถูกสร้างขึ้นโดยใช้คำสั่ง 'การเริ่มต้นอย่างรวดเร็ว' จากชุดเครื่องมือกระปุกเกียร์การสนับสนุน SQLAlchemy จะเปิดใช้งานโดยค่าเริ่มต้นโดยการตั้งค่าการกำหนดค่าต่อไปนี้ -
config['use_sqlalchemy'] = True
config['sqlalchemy.url'] = 'sqlite:///devdata.db'
โครงการ 'เริ่มต้นอย่างรวดเร็ว' ยังสร้างแพ็คเกจโมเดลภายใน ตัวอย่างเช่นโครงการ 'Hello' จะมี Hello \ hello \ model ไฟล์ต่อไปนี้ถูกสร้างขึ้นในแพ็คเกจนี้ -
__init__.py- นี่คือที่ตั้งค่าการเข้าถึงฐานข้อมูล โมเดลอ็อบเจ็กต์ของแอ็พพลิเคชันถูกอิมพอร์ตในโมดูลนี้ นอกจากนี้ยังมี DBSession ซึ่งเป็นตัวจัดการเซสชันทั่วโลกและ DeclarativeBase ซึ่งเป็นคลาสพื้นฐานสำหรับคลาสโมเดลทั้งหมด
auth.py- นี่คือที่ที่กำหนดโมเดลที่ใช้โดยสแต็กการพิสูจน์ตัวตน โมเดลฐานข้อมูลเพิ่มเติมจะถูกเก็บไว้ในแพ็คเกจนี้เป็นโมดูลแยกต่างหากและเพิ่มใน __init__.py
ให้เราเพิ่มโมเดลนักเรียนซึ่งจะสร้างตารางนักเรียนในไฟล์ 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)
คุณสามารถใช้ตัวกรองกับชุดระเบียนที่ดึงมาโดยใช้แอตทริบิวต์ตัวกรอง ตัวอย่างเช่นในการดึงข้อมูลที่มี 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) เพิ่มการแมปฟังก์ชัน '/ add' URL ต่อไปนี้ -
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 directive เทมเพลต 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 ด้านล่าง -
โชว์กริด ()
@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 ตรวจสอบให้แน่ใจว่าคุณนำเข้าฟังก์ชันเลขหน้าจาก tg.decorators ไปยังโค้ดของคุณ
Rewrite 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: สำหรับคำสั่ง รหัสสำหรับเทมเพลตนี้ควรเป็นดังนี้ -
<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ในเบราว์เซอร์ หน้าแรกของระเบียนในตารางจะปรากฏขึ้น ด้านบนของตารางนี้ยังมีลิงก์ไปยังหมายเลขหน้า
วิธีเพิ่ม Pagination Support ใน 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 ในแอปพลิเคชันที่เพิ่งเริ่มต้นใหม่
โดยค่าเริ่มต้นผู้ดูแลระบบจะให้การเข้าถึงที่สร้างขึ้นโดยอัตโนมัติสำหรับโมเดลทั้งหมดที่นำเข้าในโมเดลโครงการของคุณ / __ init__.py
วิธีสร้าง TurboGears Admin
ผู้ดูแลระบบ TurboGears เริ่มต้นถูกสร้างขึ้นเป็นวัตถุของคลาส AdminController -
from tgext.admin.controller import AdminController
class RootController(BaseController):
admin = AdminController(model, DBSession, config_type = TGAdminConfig)
สิ่งนี้จะสร้างผู้ดูแลระบบสำหรับทุกรุ่นด้วยการกำหนดค่าผู้ดูแลระบบ TurboGears เริ่มต้น
ผ่านผู้จัดการผู้ใช้ถูกสร้างขึ้นในระหว่างขั้นตอนการตั้งค่า ตอนนี้คุณสามารถเข้าถึง TurboGears Admin ได้ที่http://localhost:8080/adminครั้งแรกที่เข้าถึงหน้านี้จะขอการตรวจสอบสิทธิ์ คุณสามารถระบุชื่อผู้ใช้และรหัสผ่านของผู้ใช้ที่คำสั่งตั้งค่าแอปสร้างขึ้นสำหรับเรา -
Username: manager
Password: managepass
ในการล็อกอินเข้าสู่โปรเจ็กต์ที่เริ่มต้นอย่างรวดเร็วให้เพิ่มฟังก์ชันต่อไปนี้ในคลาส RootController (ตัวควบคุม / 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 -
รุ่นผู้ใช้
โมเดลผู้ใช้ประกอบด้วยการออกแบบตาราง 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 ซึ่งมิดเดิลแวร์เพื่อแสดงหน้าล็อกอินโดยอนุญาตให้ผู้ใช้ล็อกอินและเปลี่ยนเส้นทาง ผู้ใช้กลับไปที่หน้าที่ถูกต้องเมื่อดำเนินการเสร็จสิ้น
เงื่อนไขหรือเพรดิเคตที่แตกต่างกันที่กำหนดไว้ในโมดูล tg.predicates คือ -
ซีเนียร์ | 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 ซึ่งเป็น Object Document Mapper API การใช้ Ming คล้ายกับ SQLAlchemy มาก ภาษาคิวรี Ming ทำให้สามารถพอร์ตโครงการ TurboGears ที่ใช้ SQLAlchemy ไปยัง Ming
PyMongo คืออะไร
PyMongo เป็นการแจกจ่าย Python ที่มีเครื่องมือสำหรับทำงานกับ MongoDB หมิงขยายการให้บริการ PyMongo -
- แบบจำลองการประกาศ
- การตรวจสอบสคีมาและการแปลง
- Schema Evolution
- การใช้งาน MongoDB InMemory Pure
- หน่วยงาน
- แผนที่ประจำตัว
- ความสัมพันธ์แบบหนึ่งต่อกลุ่มแบบกลุ่มต่อหนึ่งและแบบหลายต่อหลายคน
ก่อนอื่นคุณต้องดาวน์โหลดและติดตั้ง 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 shell ให้ใช้คำสั่งต่อไปนี้ -
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. ซึ่งขึ้นอยู่กับ: ผู้ใช้กลุ่มและการอนุญาต
การกำหนดคอลเลกชันของคุณ
โดยค่าเริ่มต้น TurboGears จะกำหนดค่า Ming ในโหมดประกาศ สิ่งนี้คล้ายกับการสนับสนุนที่ประกาศของ SQLAlchemy และต้องการให้แต่ละโมเดลสืบทอดจากคลาส MappedClass
MappedClass ต้องการให้มีคลาสย่อย __mongometa__ อยู่ภายในซึ่งจะให้รายละเอียดเพิ่มเติมเกี่ยวกับชื่อของคอลเล็กชันที่จัดเก็บเอกสารและเซสชันที่ใช้ในการจัดเก็บเอกสาร
MappedClass ยังมีคำจำกัดความของเขตข้อมูลในเอกสาร โมดูล odm ของ Ming มีคำจำกัดความของคุณสมบัติฟิลด์ประเภทต่างๆ -
- 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 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 -
สวัสดี \ 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')
ใน URL Rootcontroller '/ add' ของแอปพลิเคชันที่เรียกใช้ฟังก์ชัน add () ซึ่งจะเปิดแบบฟอร์มที่ออกแบบไว้ด้านบนในเบราว์เซอร์ ปุ่มส่งจากนั้นเรียกใช้ฟังก์ชัน save_record () จะดึงข้อมูลแบบฟอร์มและบันทึกไว้ในตารางนักเรียนและเปลี่ยนเส้นทางแอปพลิเคชันไปยัง URL '/ listrec' ซึ่งจะแสดงเทมเพลตรายชื่อนักเรียน
root.py สำหรับกิจกรรมนี้มีดังนี้ -
สวัสดี / 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 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")
เทมเพลตต่อไปนี้สร้างขึ้นในโฟลเดอร์เทมเพลต -
สวัสดี \ template \ 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>
สวัสดี \ template \ 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 อย่างรวดเร็ว แอปพลิเคชันที่สร้างโดยคำสั่ง Quickstart ของกระปุกเกียร์มีเทมเพลตโครงกระดูกในโฟลเดอร์โมเดล (model.py.template) โฟลเดอร์เทมเพลต (template.html.template) และโฟลเดอร์คอนโทรลเลอร์ (controller.py.template) ไฟล์ ".template" เหล่านี้ใช้เป็นพื้นฐานในการสร้างโครงร่างใหม่สำหรับแอปพลิเคชัน
ตัวอย่างเช่นในการสร้างโมเดลใหม่ชื่อ mymodel เพียงเรียกใช้คำสั่งต่อไปนี้ -
gearbox scaffold model mymodel
คำสั่งนี้จะสร้าง model / 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 เพิ่มบรรทัดเหล่านี้ในตัวควบคุม \ root.py -
From hello.controller.mymodel import MymodelController
class RootController(BaseController): mymodel = MymodelController()
เทมเพลต scaffold template \ mymodel.html จะถูกสร้างขึ้นในโฟลเดอร์ template ด้วย จะทำหน้าที่เป็นหน้าดัชนีสำหรับ 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 และ Controller เพื่อให้สามารถขยายคอนโทรลเลอร์ได้เหมือนมัณฑนากร ดังนั้นจึงสามารถแนบกับแอปพลิเคชันคอนโทรลเลอร์ของ บริษัท อื่นได้
Application Wrapper - คล้ายกับมิดเดิลแวร์ WSGI แต่ทำงานในบริบท TurboGears เท่านั้น
ในบทนี้เราจะพูดถึงวิธีการใช้ตะขอภายในแอปพลิเคชันที่มีอยู่
ตะขอ
Hooks เป็นเหตุการณ์ที่ลงทะเบียนในไฟล์คอนฟิกูเรชันของแอปพลิเคชัน app_cfg.py. จากนั้นตัวควบคุมใด ๆ จะถูกเชื่อมต่อกับเหตุการณ์เหล่านี้โดยผู้ตกแต่งเหตุการณ์
ตะขอต่อไปนี้กำหนดไว้ใน TurboGears -
ซีเนียร์ | ตะขอและคำอธิบาย |
---|---|
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 เรียกว่าก่อนที่จะแสดงเทมเพลตคอนโทรลเลอร์เอาต์พุตคือค่าส่งคืนคอนโทรลเลอร์ |
9 | after_render เรียกว่าหลังจากเสร็จสิ้นการเรนเดอร์เทมเพลตคอนโทรลเลอร์ |
ลงทะเบียน Hook
เพื่อที่จะ register a Hook, สร้างฟังก์ชันใน app_cfg.py จากนั้นลงทะเบียนโดยใช้รหัสต่อไปนี้ -
tg.hooks.register(hookane, function, controller)
ในโค้ดต่อไปนี้ on_startup, on_shutdown และ before_render hooks จะถูกลงทะเบียนใน 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 hook ถูกลงทะเบียนด้วยฟังก์ชันคอนโทรลเลอร์ใน 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 hook จะแสดงบนคอนโซล
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)
หากเราเปิดเซิร์ฟเวอร์โดยใช้คำสั่งเซิร์ฟเวอร์กระปุกการแจ้งเตือนของส่วนขยายที่ลงทะเบียนใหม่สามารถดูได้บนคอนโซลดังต่อไปนี้ -
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 - ซึ่งจะดำเนินการเมื่อเรียกใช้การตั้งค่าแอป
Statics - ซึ่งจะมีอยู่ในเส้นทางส่วนตัวของพวกเขาเอง
ติดตั้งแอปพลิเคชัน plugtest นี้และติดตั้งเหมือนกันโดยทำการแก้ไขต่อไปนี้ใน app_cfg.py.
from tgext.pluggable import plug
plug(base_config, plugtest)
REST ย่อมาจาก REการนำเสนอ State Tเรียกค่าไถ่ REST เป็นสถาปัตยกรรมตามมาตรฐานเว็บและใช้โปรโตคอล HTTP สำหรับการสื่อสารข้อมูล มันหมุนรอบทรัพยากรที่ทุกองค์ประกอบเป็นทรัพยากรและทรัพยากรถูกเข้าถึงโดยอินเทอร์เฟซทั่วไปโดยใช้วิธีมาตรฐาน HTTP REST เปิดตัวครั้งแรกโดยRoy Fielding in 2000.
RestController คืออะไร
RestController ใน TurboGears มีกลไกในการเข้าถึงเมธอดของคำขอไม่ใช่แค่ URL คำกริยามาตรฐาน HTTP ประกอบด้วย: GET, POST, PUT และ DELETE RestController รองรับสิ่งเหล่านี้และยังเพิ่มทางลัดบางอย่างสำหรับการจัดส่ง URL ที่ทำให้การแสดงข้อมูลเป็นแบบฟอร์มและรายการทำให้ผู้ใช้ง่ายขึ้นเล็กน้อย
เพื่ออธิบายว่า RESTful ทำงานร่วมกับ TurboGears อย่างไรเราจะกำหนดบริการเว็บแบบง่ายๆที่แสดงรายชื่อนักเรียน
รหัสสำหรับรุ่นนักเรียนได้รับด้านล่าง -
model \ 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 ที่พัฒนาโดย Graham Dumpleton อนุญาตให้ใช้โปรแกรม WSGI โดยใช้เว็บเซิร์ฟเวอร์ Apache
ประการแรกติดตั้ง Apache 2.X สำหรับแพลตฟอร์มของคุณหากยังไม่ได้ดำเนินการ เมื่อคุณติดตั้ง Apache แล้วให้ติดตั้ง mod_wsgi สร้างและเปิดใช้งานสภาพแวดล้อมเสมือน Python บนเซิร์ฟเวอร์และติดตั้ง TurboGears ในนั้น
ติดตั้งแอปพลิเคชันของคุณภายใน Application Director จากนั้นสร้างสคริปต์ชื่อ 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 และ Chaussette
Circus เป็นผู้จัดการกระบวนการและซ็อกเก็ต สามารถใช้เพื่อตรวจสอบและควบคุมกระบวนการและซ็อกเก็ต เมื่อจับคู่กับเซิร์ฟเวอร์ Chaussette WSGI จะกลายเป็นเครื่องมือที่มีประสิทธิภาพในการปรับใช้แอปพลิเคชันของคุณและจัดการกระบวนการที่เกี่ยวข้องกับแอปพลิเคชันของคุณ
TurboGears - GoogleAppEngine
ติดตั้ง Google AppEngine SDK สำหรับ Python จาก URL ต่อไปนี้ - https://cloud.google.coms
ติดตั้ง Google AppEngine ในระบบของคุณ จากนั้นเปิด Google Developer Console และลงชื่อเข้าใช้ด้วยบัญชี 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 และคลิกที่ปุ่มเรียกดูเพื่อดูว่าแอปพลิเคชันทำงานได้อย่างถูกต้องบน localhost
เราได้สร้างโปรเจ็กต์ชื่อ mytgapp ในคอนโซลนักพัฒนาซอฟต์แวร์แล้ว ตอนนี้คลิกที่ปุ่มปรับใช้ใน Launcher หลังจากกระบวนการปรับใช้เสร็จสิ้นhttp://mytgapp.appspot.com/ เยี่ยมชมเพื่อดูใบสมัครของเราทางออนไลน์