IronPython 个人网站样例----宝藏挖掘
http://blog.joycode.com/scottgu/archive/2006/11/18/86737.aspx,才让我发现了这个宝库。
今天下午花了点时间学习了一下,收获不少。记录在这里。
IronPython 版本的 Personal Web Site Starter Kit 是一个代码样例。我们用 Visual Studio 创建一个网站项目时,选择该模版就可以创建自己的网站项目了。下面我简单的说说该项目中一些值得学习的东西。
1. 数据访问:IronPython 版本的 SqlHelper
我们知道,IronPython for ASP.NET 提供了 App_Script 目录作为公用代码存放的地方,类似于 C# 或 VB.NET 版本的网站项目中的 App_Code 目录。在这个 Starter Kit 中,App_Script 目录下只包含了一个文件 PhotoManager.py,这是一个包含了所有公用代码的模块。其实从代码组织的方式来说,我觉得这么弄不太合适,因为像 SqlHelper 类,数据访问方法,实体类等内容全都定义在这里面了,没有做到一个类一个文件。不过因为 Python 的语法非常简单(比起 C# 而言),这个文件中的代码也不多,也没有给阅读带来太大的障碍。下面我们着重分析这个文件中一些可借鉴的地方。
先看看 py 版本的 SqlHelper 吧,在这里被命名成了 __sqlHelper,之所以这么命名是因为,这个类是被用作内部的帮助类的,并不会在客户端(该模块的使用者,即 importer)直接使用的,而 Python 中的模块有个特性,在使用 from moduleName import * 的语法的时候,以 "__" 开头的属性不会被导入,从而造成了被隐藏的效果。(当然这并不能阻止你通过 import moduleName 语法来使用它,或者也可以使用显式的导入语句 from moduleName import SomeAttr)。
其代码如下:
#
# 这里定义了一个 sqlHelper 帮助类,客户端并不直接调用它,
# 而是通过更高层的函数来调用。
# 注意:这个类只提供了对存储过程操作的支持。当然要扩展为普通 sql 的支持也是很容易的。
#
class __sqlHelper:
def __init__(self):
self.connection = None
self.command = None
def Open(self, commandname, sqlparams):
self.connection = SqlConnection(ConfigurationManager.ConnectionStrings['Personal'].ConnectionString)
self.command = SqlCommand(commandname, self.connection)
self.command.CommandType = CommandType.StoredProcedure
for k, v in sqlparams.items():
if not k.startswith('@'): k = '@' + k
if k == '@IsPublic' and v is None:
user = HttpContext.Current.User
v = not (user.IsInRole('Friends') or user.IsInRole('Administrators'))
self.command.Parameters.Add(SqlParameter(k, v))
self.connection.Open()
def Execute(self):
self.command.ExecuteNonQuery()
def ReadBytes(self):
result = self.command.ExecuteScalar()
if result is not None and len(result) == 0: result = None
return result
def ReadList(self, itemtype):
list = []
reader = self.command.ExecuteReader()
try:
while reader.Read(): list.Add(itemtype(reader))
finally:
reader.Close()
return list
def Close(self):
if self.command is not None: self.command.Dispose()
if self.connection is not None: self.connection.Close()
这个类不多说。既然我说了这个类不是让客户端直接使用的,那么包装它的函数在哪里呢,请看:
# 下面是利用 __sqlHelper 类创建的几个快捷的数据库操作函数
#
# 执行 sp,不返回结果
def SqlExecute(command, **args):
sql = __sqlHelper()
try:
sql.Open(command, args)
sql.Execute()
finally:
sql.Close()
# 执行 sp 并返回 scalar 信息
def SqlSelectBytes(command, **args):
result = None
sql = __sqlHelper()
try:
sql.Open(command, args)
result = sql.ReadBytes()
finally:
sql.Close()
return result
# 执行 sp,并返回多个实体的列表,itemtype 是实体类型
def SqlSelectList(itemtype, command, **args):
result = None
sql = __sqlHelper()
try:
sql.Open(command, args)
result = sql.ReadList(itemtype)
finally:
sql.Close()
return result
下面我列举几个使用这些数据访问函数的例子,都非常简单:
我们看到,利用 Python 可以传递字典参数的特性,这里的语法比 C# 简单太多了!一句话就搞定了一个数据访问方法。这里参数列表里面的参数会被上面讲过的 __sqlHelper 内部组合为 @ 开头的 SqlCommand 的参数名称。非常直接了当。而 SqlExecute 的第一个参数就是需要执行的存储过程的名称。
2. 实体类的简单定义
这个简单的不值一提,看代码:
#
# 相片实体类
class Photo:
def __init__(self, reader):
self.PhotoID= int(reader['PhotoID'])
self.AlbumID = int(reader['AlbumID'])
#self.Caption = str(reader['Caption'])
self.Caption = reader['Caption'].ToString()
# 相册实体类
class Album:
def __init__(self, reader):
self.AlbumID = int(reader['AlbumID'])
self.Count = int(reader['NumberOfPhotos'])
# self.Caption = str(reader['Caption'])
self.Caption = reader['Caption'].ToString()
self.IsPublic = bool(reader['IsPublic'])
但是,请注意我上面黄色加亮的几行代码,被注释掉的是原先官方提供代码里面的,而下面一行是我修改过的代码。这里是我学习过程中发现的一个小小的 bug. 如果采用原来的代码,则会碰到一个问题。如果 reader 这个数据行里面该字段的信息是含有中文的,str 函数就不能正确转换。你会碰到如下的情况:
按照上面的方法修改之后,中文就可以正常的读出来了:
3. 可被我们复用的缩略图函数
这是我们可以从这个 Starter Kit 里挖到的又一个宝藏:
def ResizeImageFile(imageFile, targetSize):
oldImage = Image.FromStream(MemoryStream(imageFile))
try:
newSize = CalculateDimensions(oldImage.Size, targetSize)
newImage = Bitmap(newSize.Width, newSize.Height, PixelFormat.Format24bppRgb)
try:
canvas = Graphics.FromImage(newImage)
try:
canvas.SmoothingMode = SmoothingMode.AntiAlias
canvas.InterpolationMode = InterpolationMode.HighQualityBicubic
canvas.PixelOffsetMode = PixelOffsetMode.HighQuality
canvas.DrawImage(oldImage, Rectangle(Point(0, 0), newSize))
m = MemoryStream()
newImage.Save(m, ImageFormat.Jpeg)
result = m.GetBuffer()
finally:
canvas.Dispose()
finally:
newImage.Dispose()
finally:
oldImage.Dispose()
return result
# 按缩放逻辑计算图片的新尺寸
def CalculateDimensions(oldSize, targetSize):
newSize = Size()
if oldSize.Height > oldSize.Width:
newSize.Width = int(float(oldSize.Width*targetSize)/oldSize.Height)
newSize.Height = targetSize
else:
newSize.Width = targetSize
newSize.Height = int(float(oldSize.Height*targetSize)/oldSize.Width)
return newSize
这个例子里面,所有的图片都是用二进制的方式保存在数据库里面的。其字段类型为 image. 所以我们看到上述函数操作中,返回的是表示图片内容的字节流信息。
4. 自定义 HttpHandler 来处理图片输出
Web_Handler.py 是负责输出图片二进制内容的一个 HttpHandler. 这个文件从当前 Request 对象的 QueryString 中分析信息,得到当前指定的图片 id, 然后去读取数据库中的图片二进制流并输出之。其中还使用了缓存策略以提高性能。看代码:
import PhotoManager
SizeMappings = {'S':PhotoManager.SmallSize, 'M':PhotoManager.MediumSize, 'L':PhotoManager.LargeSize}
# 这个 http handler 负责输出图片信息,其内部有缓存机制。
def ProcessRequest(context):
request = context.Request
response = context.Response
size = SizeMappings.get(request.Size, PhotoManager.OriginalSize)
try:
if request.PhotoID is not None:
id = int(request.PhotoID)
bytes = PhotoManager.GetPhoto(id, size)
else:
id = int(request.AlbumID)
bytes = PhotoManager.GetFirstPhoto(id, size)
except:
bytes = None
# 如果读取失败或者找不到图片,则输出占位符图片
if bytes == None:
bytes = PhotoManager.GetPhotoPlaceHolder(size)
response.ContentType = "image/jpeg"
# 注意这里使用了缓存策略
response.Cache.SetCacheability(HttpCacheability.Public)
response.OutputStream.Write(bytes, 0, len(bytes))
于是乎,有了这个 HttpHandler,我们要输出图片就很简单了,看一个例子:
5. SiteMap 的节点自定义解析函数
SiteMap 默认只能利用静态的 Web.sitemap 文件中定义好的节点层次,并且每个节点的 url 也是固定的,通过处理 SiteMapResolve 事件,我们可以动态修改节点的 url. 这个实现定义在 Global.py 中,顺便可以看一下 IronPython 中的 Global 文件应该怎样写的:
from System.Web import *
from System.Web.Security import *
def Application_Start():
SiteMap.SiteMapResolve += AppendQueryString
if not Roles.RoleExists('Administrators'): Roles.CreateRole('Administrators')
if not Roles.RoleExists('Friends'): Roles.CreateRole('Friends')
def AppendQueryString(sender, e):
node = SiteMap.CurrentNode
if node is not None:
node = node.Clone(True)
qs = e.Context.Request.QUERY_STRING
if len(qs) > 0:
node.Url += '?' + qs
if node.ParentNode is not None:
node.ParentNode.Url += '?' + qs
return node
6. 享受 IronPython 的便利,简化页面后台代码
IronPython for ASP.NET 的引擎实现了很多便利的特性,这个在白皮书中已经提及。比如不用写 FindControl 了,获取 QueryString 变得方便了,等等。下面的代码是一个 GridView 的 CRUD 事件处理的后台代码:
多么简单!
从这个例子中,我们还可以学到其他一些 ASPX 页面级别的技巧。
比如新增信息的功能,通过 FormView 控件的 InsertItemTemplate 来实现就非常方便。另外,则页面中做数据绑定时,可以通过这样的语法 <%# Container.DataItemIndex %> 来取得记录 ID. 我们平时用的最多的可能是 Container.DataItem 了,但 DataItemIndex 这个属性估计用的人是不多的。
另一个技巧,要在页面回发后维持当前页面的滚动高度,只要在 Page_Load 里面这样写:
在 IronPython for ASP.NET 带给我们兴奋的同时,我们也要看到,目前由于缺乏 Intellisense 的支持,我都不知道这么多代码要能正确编写出来需要花费多少调试的精力。希望很快能够下载到正式版本。
出处:http://www.cnblogs.com/RChen/archive/2006/11/18/ipy_starterkit.html
IronPython 个人网站样例----宝藏挖掘的更多相关文章
- Orchard运用 - 网站样例
在此分享一些个人觉得比较不错的基于Orhcard搭建的网站. 中文版: http://www.58img.com/ http://www.weijiqiong.com/ http://www.apma ...
- Ajax框架,DWR介绍,应用,样例
使用Ajax框架 1. 简化JavaScript的开发难度 2. 解决浏览器的兼容性问题 3. 简化开发流程 经常使用Ajax框架 Prototype 一个纯粹的JavaScript函数库,对Ajax ...
- MapGuide应用程序演示样例——你好,MapGuide!
图 3‑4显示了基于MapGuide的Web应用程序的开发流程,整个开发流程能够分为五个阶段.图中,矩形代表任务,椭圆形被任务使用的或被任务创建的实体,箭头代表数据流. 1) 载入文件类型的数据,配置 ...
- scrapy爬虫学习系列二:scrapy简单爬虫样例学习
系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备: http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...
- [转][LoadRunner]LR性能测试结果样例分析
LR性能测试结果样例分析 测试结果分析 LoadRunner性能测试结果分析是个复杂的过程,通常可以从结果摘要.并发数.平均事务响应时间.每秒点击数.业务成功率.系统资源.网页细分图.Web服务器资源 ...
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
- [LoadRunner]LR性能测试结果样例分析
R性能测试结果样例分析 测试结果分析 LoadRunner性能测试结果分析是个复杂的过程,通常可以从结果摘要.并发数.平均事务响应时间.每秒点击数.业务成功率.系统资源.网页细分图.Web服务器资源. ...
- LoadRunner性能测试样例分析
LR性能测试结果样例分析 测试结果分析 LoadRunner性能测试结果分析是个复杂的过程,通常可以从结果摘要.并发数.平均事务响应时间.每秒点击数.业务成功率.系统资源.网页细分图.Web服务器资源 ...
- Tomcat样例安全漏洞
[漏洞描述] Tomcat在使用的时候一般都直接官网下载源代码包直接使用. 默认情况下,Tomcat源码包里面包含了 examples 这个目录,这个目录主要实现一些样例页面的访问. 比如: ...
随机推荐
- 九度OJ 1202:排序 (排序)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:19711 解决:6508 题目描述: 对输入的n个数进行排序并输出. 输入: 输入的第一行包括一个整数n(1<=n<=100). ...
- 9.接口BeanPostProcessor
package org.springframework.beans.factory.config; import org.springframework.beans.BeansException; p ...
- 2.设计模式---Adapter模式
Adapter模式也就是适配器模式,最常见的就是这个:码农必备-------------->笔记本电源适配器: 那么这玩意到底是干嘛的?? 手工画图一张: 220V--------------- ...
- 让intellij挂在异常处,特别是出现null pointer的地方
1 在Intellij中设置java exception breakpoint 在调试模式下,run->view breakpoints 在java exception breakpoints- ...
- 核函数 深度学习 统计学习 强化学习 神经网络 xx
- iOS 开发与H5交互(JavaScriptCore框架的使用)
现在的iOS项目中嵌入了越来越多的Web界面,当然是为了方便,那么为了迎合这一趋势,作为iOS开发程序员,我们必须要了解怎么样用OC去和这些Web界面进行交互.这里介绍的是JavaScriptCore ...
- jquery点击一组按钮中的一个,跳转至对应页面处理策略。(如点击订单列表中的一个订单,跳转至该订单的详情)
将改组按钮的数据设置一个相同的属性(如class),然后每个按钮设置不同的id 当用户点击属性为class的按钮,根据id属性来判断点击的是哪个按钮,然后进行相关操作. 代码示例: <scrip ...
- Python菜鸟之路:Python基础——函数
一.函数 1. 简介 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率. 2. 组成 函数代码块以 def 关键词开头,后接函数名和圆括号( ...
- Android笔记之获取debug.keystore和release.keystore的MD5/SHA1值
获取debug.keystore的key,如下图 获取release.keystore的key 输入命令keytool -list -v -keystore <jksFilename> 例 ...
- Django模型系统——ORM表结构对应关系
对于数据库来说一般表结构只会有三种对应关系,分别是一对一.一对多和多对一,下面分别介绍: 1.一对多 何为一对多,例如一个学生只可能有一个班级,一个班级却又多个学生,班级表和学生表就是一对多的关系. ...