TurboGears - 使用MongoDB



TurboGears 也支持 MongoDB 文档数据库。它使用 Ming,一个对象文档映射器 API。Ming 的用法与 SQLAlchemy 非常相似。Ming 查询语言使得将基于 SQLAlchemy 的 TurboGears 项目移植到 Ming 成为可能。

什么是 PyMongo

PyMongo 是一个 Python 发行版,包含用于处理 MongoDB 的工具。Ming 扩展了 PyMongo,提供:

  • 声明式模型
  • 模式验证和转换
  • 模式演变
  • 纯内存 MongoDB 实现
  • 工作单元
  • 标识映射
  • 一对多、多对一和多对多关系

首先,你需要下载并安装 MongoDB。最新的 MongoDB 发行版可以从 https://www.mongodb.org/downloads 下载

在 Windows 上,通过提供 -dbpath 选项启动 MongoDB 服务器:

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

D:\mongo 文件夹被指定用于存储 MongoDB 数据库。服务器开始监听 https://127.0.0.1:27017。现在,要启动 MongoDB shell,请使用以下命令:

C:\mongodb\bin>Mongo

我们的 MongoDB 环境现在已经准备好了。

现在使用 -ming 选项创建一个 TurboGears 项目:

gearbox quickstart --ming Hello

这个快速启动项目将提供一个身份验证和授权层,类似于 SQLAlchemy 版本提供的那个。此应用程序现在将尝试连接到本地机器端口 27017 上的服务器。项目文件夹中的 development.ini 文件包含以下设置:

ming.url = mongodb://127.0.0.1:27017/
ming.db = hello

使用以下命令设置项目:

Python setup.py develop

项目文件夹包含 models 子文件夹,其中包含以下文件:

  • __init__.py - 这是设置数据库访问的地方。你的集合应该导入到这个模块中。例如,我们将在该包中添加 student 集合。

  • session.py - 此文件定义了数据库连接的会话。每次必须声明MappedClass以指定会话来执行查询时,都需要导入它。

  • auth.py - 如果你在快速启动中启用了身份验证和授权,则会创建此文件。它定义了三个集合repoze.who,它进一步依赖于:User、Group 和 Permission。

定义你的集合

默认情况下,TurboGears 以声明模式配置 Ming。这类似于 SQLAlchemy 的声明式支持,需要每个模型都继承自 MappedClass 类。

MappedClass 要求内部提供一个 __mongometa__ 子类,该子类进一步提供有关存储文档的集合名称和用于存储文档的会话的详细信息。

MappedClass 还包含文档中字段的定义。Ming 的 odm 模块定义了不同类型的字段属性:

  • FieldProperty
  • ForeignIdProperty
  • RelationProperty

ming.schema 模块定义了以下数据类型:

  • ming.schema.Anything
  • ming.schema.Array
  • ming.schema.Binary
  • ming.schema.Bool
  • ming.schema.Float
  • ming.schema.Int
  • ming.schema.ObjectId
  • ming.schema.Scalar
  • ming.schema.String

要在此模型中添加 student 集合,请将以下代码另存为 hello/models 文件夹中的 student.py。

Hello\models\student.py

from ming import schema
from ming.odm import MappedClass
from ming.odm import FieldProperty, ForeignIdProperty
from hello.model import DBSession
   
Class student(MappedClass):
   class __mongometa__:
      session = DBSession
      name = 'student'
      
   _id = FieldProperty(schema.ObjectId)
   name = FieldProperty(schema.String(required = True))
   city = FieldProperty(schema.String(if_missing = ''))
   address = FieldProperty(schema.String(if_missing = ''))
   pincode = FieldProperty(schema.String(if_missing = ''))

最后,将此模型包含在 hello\models\__init__.py 中

# Import your model modules here.
from hello.model.auth import User, Group, Permission
from hello.model.student import student

要设置这些模型,请运行以下 gearbox 命令:

Gearbox setup-app

使用以下 gearbox 命令启动服务器:

Gearbox serve –reload –debug

打开此应用程序的主页 (https://127.0.0.1:8080/) 并使用管理员凭据登录。此应用程序的管理页面将显示已设置的模型列表。(用户名:manager,密码:managepass)

Homepage Application

也可以在 MongoDB Web 界面以及 MongoDB shell 中验证集合的创建。

ODMSession 用于使用以下函数执行多个数据库操作:

  • model.query.find()
  • model.query.find_and_modify()
  • model.remove()
  • model.update()
  • model.flush()

设计 ToscoWidget 表单

我们现在将设计一个 ToscoWidget 表单来输入学生数据并将其添加到 student 模型的基础表中。

以下是创建 studentform.py 的代码:

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 '/add' URL 中调用 add() 函数,该函数将在浏览器中打开上面设计的表单。然后,其提交按钮将调用 save_record() 函数。它检索表单数据并将其保存到 student 表中,然后将应用程序重定向到 '/listrec' URL,该 URL 公开了 studentlist 模板。

此活动的 root.py 如下所示:

Hello/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")

以下模板是在 templates 文件夹中创建的:

Hello\templates\studentform.html

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:py = "http://genshi.edgewall.org/" lang = "en">
	
   <head>
      <title>Student Registration Form</title>
   </head>
	

   <body>
      <div id = "getting_started">
         ${form.display(value = dict(title = 'Enter data'))}
      </div>
   </body>
	
</html>

Hello\templates\studentlist.html

<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:py = "http://genshi.edgewall.org/">

   <head>
      <link rel = "stylesheet" type = "text/css" media = "screen" 
         href = ${tg.url('/css/style.css')}" />
      <title>Welcome to TurboGears</title>
   </head>
   
   <body>
      <h1>Welcome to TurboGears</h1>
		
      <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)">
         <div py:if = "flash" py:replace = "Markup(flash)" />
      </py:with>
      
      <h2>Current Entries</h2>
		
      <table border = '1'>
         <thead>
            <tr>
               <th>Name</th>
               <th>City</th>
               <th>Address</th>
               <th>Pincode</th>
            </tr>
         </thead>
         
         <tbody>
            <py:for each = "entry in entries">
               <tr>
                  <td>${entry.name}</td>
                  <td>${entry.city}</td>
                  <td>${entry.address}</td>
                  <td>${entry.pincode}</td>
               </tr>
            </py:for>
         </tbody>
      </table>
		
   </body>
	
</html>

重新启动服务器并在浏览器中输入 https://127.0.0.1:8080/add

Student Registration Form

每次添加数据并按下提交按钮时,都将显示当前条目的列表。

New Entry Output
广告