IronPython 个人网站样例----宝藏挖掘

news/2024/5/20 22:21:01/文章来源:https://blog.csdn.net/weixin_30631587/article/details/98336095
IronPython for ASP.NET 的 CTP 已经发布两个多星期了,惭愧的是,因为工作繁忙,一直没有太多时间来学习。居然忽略了 Personal Web Site Starter Kit 的 IronPython 样例。幸亏了 Scott Guthrie 这篇博客:
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)。
其代码如下:
# Internal SQL Helper
#
#
 这里定义了一个 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

下面我列举几个使用这些数据访问函数的例子,都非常简单:
# Album-Related Methods

# 获得所有相册的列表
def GetAlbums():
    
return SqlSelectList(Album, 'GetAlbums', IsPublic=None)

# 添加相册
def AddAlbum(caption, ispublic):
    SqlExecute(
'AddAlbum', Caption=caption, IsPublic=ispublic)

# 删除相册
def RemoveAlbum(albumid):
    SqlExecute(
'RemoveAlbum', AlbumID=albumid)

# 更新相册信息
def EditAlbum(caption, ispublic, albumid):
    SqlExecute(
'EditAlbum', Caption=caption, IsPublic=ispublic, AlbumID=albumid)

# 获取一个随机的相册编号
def GetRandomAlbumID():
    albums 
= GetAlbums()
    
if len(albums) == 0: return -1
    
return albums[Random().Next(len(albums))].AlbumID

我们看到,利用 Python 可以传递字典参数的特性,这里的语法比 C# 简单太多了!一句话就搞定了一个数据访问方法。这里参数列表里面的参数会被上面讲过的 __sqlHelper 内部组合为 @ 开头的 SqlCommand 的参数名称。非常直接了当。而 SqlExecute 的第一个参数就是需要执行的存储过程的名称。

2. 实体类的简单定义

这个简单的不值一提,看代码:
# 下面定义了两个实体类,它们都提供了从 DataReader 中获取信息来填充自身字段的构造函数。(但是其实不限于 DataReader, 应该说是任意的 dict 都可以。)
#
#
 相片实体类
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 函数就不能正确转换。你会碰到如下的情况:

ipy_starterkit_bug.JPG

按照上面的方法修改之后,中文就可以正常的读出来了:

ipy_starterkit_good.JPG




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, 然后去读取数据库中的图片二进制流并输出之。其中还使用了缓存策略以提高性能。看代码:
from System.Web import *
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,我们要输出图片就很简单了,看一个例子:
<img src="../Web_Handler.py?PhotoID=<%# PhotoID %>&Size=L" class="photo_198" style="border:4px solid white" alt='Photo Number <%# PhotoID %>' />


5. SiteMap 的节点自定义解析函数

SiteMap 默认只能利用静态的 Web.sitemap 文件中定义好的节点层次,并且每个节点的 url 也是固定的,通过处理 SiteMapResolve 事件,我们可以动态修改节点的 url. 这个实现定义在 Global.py 中,顺便可以看一下 IronPython 中的 Global 文件应该怎样写的:

from System import *
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 事件处理的后台代码:
def GridView1_RowDeleting(sender, e):
    id 
= GridView1.DataKeys[e.RowIndex].Value
    PhotoManager.RemovePhoto(id)

def GridView1_RowEditing(sender, e):
    GridView1.EditIndex 
= e.NewEditIndex

def GridView1_RowCancelingEdit():
    GridView1.EditIndex 
= -1

def GridView1_RowUpdating(sender, e):
    caption 
= GridView1.Rows[e.RowIndex].CaptionTextBox.Text
    id 
= GridView1.DataKeys[e.RowIndex].Value
    
    PhotoManager.EditPhoto(caption, id)
    
    GridView1.EditIndex 
= -1

多么简单!

从这个例子中,我们还可以学到其他一些 ASPX 页面级别的技巧。
比如新增信息的功能,通过 FormView 控件的 InsertItemTemplate 来实现就非常方便。另外,则页面中做数据绑定时,可以通过这样的语法 <%# Container.DataItemIndex %> 来取得记录 ID. 我们平时用的最多的可能是 Container.DataItem 了,但 DataItemIndex 这个属性估计用的人是不多的。
另一个技巧,要在页面回发后维持当前页面的滚动高度,只要在 Page_Load 里面这样写:
MaintainScrollPositionOnPostBack = True


在 IronPython for ASP.NET 带给我们兴奋的同时,我们也要看到,目前由于缺乏 Intellisense 的支持,我都不知道这么多代码要能正确编写出来需要花费多少调试的精力。希望很快能够下载到正式版本。

 

出处:http://www.cnblogs.com/RChen/archive/2006/11/18/ipy_starterkit.html

转载于:https://www.cnblogs.com/mq0036/p/5014337.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_822314.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

35个富有启发和美丽的红色网站案例

网站设计是设计师的具有挑战性的任务。&#xff0c;他们设计的网站&#xff0c;即他们应该选择什么颜色风格来进行网站设计&#xff0c;这是每一个网站设计最重要的部分。颜色总是定义您的网站的性质。 有各种颜色的网站&#xff0c;如蓝色&#xff0c;绿色&#xff0c;灰色&am…

AX 2012 安装EP时提示网站模板“AXSITEDEF#0”的文件或参数无效

问题 在Dynamics AX 2012 安装Enterprise Portal 时最后配置阶段提示错误&#xff0c;信息如下&#xff1a; The site /sites/DynamicsAx could not be created. The following exception occurred: 网站模板“AXSITEDEF#0”的文件或参数无效。 参数名: WebTemplate. 仅当Busi…

minify php,php开源系统-使用Minify来优化网站性能

1 对php网站进行了搭建&#xff0c;并完成一些对图片上传的基本功能&#xff0c;服务器数据库的操作等等2 完成 首个jquery 框架中静态模板中加入 实际的函数范例&#xff1b;并了解和掌握了 sizzle.js 框架的使用流程和机制&#xff1b;并成功的在本地apache服务器站点上进行引…

现实世界的Windows Azure:专访PrivacyCentral网站创始人、CEO Zoiner Tejada

作为现实世界Windows Azure博客系列中的一部分&#xff0c;我联系了PrivacyCentral网站创始人、CEO Zoiner Tejada&#xff0c;来探寻该公司是如何利用Windows Azure平台及Ruby语言来搭建其强大的在线隐私服务。点击这里来了解PrivacyCentral的成功案例。下面我们来看看Tejada先…

PHP网站运维必知必会,运维架构师能力要求,做好运维必知必会的4个技能

一名OPS架构师&#xff0c;学习能力占了主要一部分(其实其他行业包括任何事情等等这都是关键一点)。如果这块缺失&#xff0c;仅凭一些生产线的经验教训&#xff0c;而不去反思&#xff0c;并从中总结出更多的经验来&#xff0c;想成为一个架构师那都是不现实的。那么优秀的OPS…

IIS7 网站发布常见问题及解决方案小结

把这两天发布网站遇到了一些问题总结了一下&#xff0c;希望对大家有用&#xff01; 1、不是有效的Win32位应用程序 &#xff1a; 解决方案&#xff1a; 1、进入应用程序池》选中网站》点击右侧”高级设置“》将运行32位选项改为"True" 3、在IIS如何修改.NET FrameWo…

织梦网站服务器 开启服务,WEB服务器启用了OPTIONS方法

漏洞名称&#xff1a;WEB服务器启用了OPTIONS方法危险等级&#xff1a;★☆☆☆☆(轻危)漏洞类型&#xff1a;配置错误披露时间&#xff1a;2015-09-14漏洞描述&#xff1a;攻击者可利用options方法获取服务器的信息&#xff0c;进而准备进一步攻击。解决方案&#xff1a;修改配…

使用rem来开发你的移动端网站

what is rem &#xff1f; 1&#xff09;css3中的计量元素大小的单位&#xff0c;类似px、pt、em。 2&#xff09;一种相对根元素font-size的计算方式。1rem <html>s font-size px (你懂就好) 3&#xff09;使用场景&#xff1a;每个元素的宽高、文字大小、行距、补白等…

推荐20个精美的响应式设计(Responsive Design)网站作品

响应式网页设计是时下网页设计领域最热门的话题之一&#xff0c;该概念由著名网页设计师 Ethan Marcotte 在2010年5月份提出&#xff0c;其目标是要让设计的网站能够响应用户的行为&#xff0c;根据不同终端设备自动调整尺寸。今天这篇文章向大家推荐20个优秀的响应式布局网页 …

自动录制html网站,RPA自动化软件源码,可录制操作脚本(财务处理系统)

可录制操作脚本&#xff0c;并实现 重新操作。流程录制以及自动化模拟操作。资源下载此资源下载价格为2D币&#xff0c;请先登录资源文件列表RPA/Microsoft.Office.Core.dll , 409600RPA/microsoft.office.interop.excel.dll , 1628856RPA/Microsoft.Vbe.Interop.dll , 64112RP…

Mac下配置域名和网站测试环境

一、在 /etc/hosts 下配置相关域名1, controlspace 打开spotlight, 搜索“terminal”2, 打开Terminal 3, 在terminal界面中输入: sudo vi /etc/hosts 然后回车 4, 会提示让你输入密码 XXXX.&#xff08;注意输入密码时你看不到&#xff0a;号&#xff09; 5, 输入成功以后…

linux服务器运行程序shell脚本,Linux中shell脚本怎么运行_网站服务器运行维护,linux,shell,执行...

ssh linux是什么_网站服务器运行维护ssh linux是指ssh服务&#xff0c;是一个守护进程&#xff0c;系统后台监听客户端的连接&#xff0c;ssh服务端的进程名为sshd&#xff0c;负责实时监听客户端的请求&#xff0c;包括公共秘钥等交换等信息&#xff1b;ssh服务端由openssh和o…

linux 提高 gzip 速度,如何通过gzip和nginx来提高网站打开速度及整体性能

要知道&#xff0c;网站的打开速度取决于浏览器打开下载的网页文件大小。如果传输的页面内容文件减少&#xff0c;那你网站的打开速度一定会加快。特别是手机端的用户&#xff0c;打开网站速度受限于移动端网络&#xff0c;所以压缩网站页面内容显得至关重要。gzip是一种非常流…

微信小程序新闻服务器,微信小程序新闻网站详情页

扩展运算符的巧妙应用这个template模板&#xff0c;绑定的数据带item前缀那么使用模板的时候&#xff0c;也必须保证是itemdata帮绑定数据用双花括号包住item还有wx:for-item默认也是item&#xff0c;因此可省略这样带有item不利于代码复用&#xff0c;解决方法&#xff1a;将t…

UVaLive(LA) 3902 Network,Seoul 2007

题目传送门 显然先让第一个服务器成为根节点&#xff0c;然后我们搜一遍&#xff0c;先把所有叶节点入到一vector里面&#xff0c;vector的第一维是深度&#xff0c;出来之后让最深的叶节点晚上找第k级fa&#xff0c;因为这样可以让其影响力最大&#xff0c;然后去往所有方向搜…

iBATIS 3 试用手记 - The FUTURE - ITeye技术网站

iBATIS 3 试用手记 - The FUTURE - ITeye技术网站前记&#xff1a;本来打算去CSDN写这篇文章的&#xff0c;结果CSDN的服务器又出问题了&#xff0c;登录了N次都进不去&#xff0c;郁闷&#xff0c;干脆换个Blog来写。 iBATIS以其对SQL控制的灵活性而受到许多大型项目的青睐&am…

php网站大全,【网址导航系统】基于PHP+MYSQL开发的开源网站分类目录管理系统

【网址导航系统】基于PHPMYSQL开发的开源网站分类目录管理系统DYCMS的主要特性包括&#xff1a;纯净的导航界面(去繁求简)响应式设计的前端设计聚合式搜索框(一键切换百度&#xff0c; 搜狗&#xff0c;360&#xff0c;必应搜索平台)用户可自行申请收录&#xff0c;由管理员后台…

网站与数据库不在同一服务器,不在同一个服务器里的dede数据库之间数据调用方法...

这篇文章主要为大家详细介绍了不在同一个服务器里的dede数据库之间数据调用方法&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下,有需要的朋友可以收藏方便以后借鉴。织梦dedecms数据库不在同一个服务器,数据调用方法!data/common.inc.php这个是保存数…

python爬取网站数据的小程序_基于urllib网页爬取的翻译小程序

中英互译python的urllib可谓http操作的神器&#xff0c;可以模仿浏览器的行为提交请求并收到返回的数据。笔者在此利用urllib向百度翻译发送翻译请求并获取翻译结果&#xff0c;演示一下该库的简单用法&#xff0c;小脚本封装后可以在命令行下运行&#xff0c;非常适用于linux。…