IronPython 个人网站样例宝藏挖掘

news/2024/5/13 17:22:52/文章来源:https://blog.csdn.net/inelm/article/details/4612982
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.luyixian.cn/news_show_899183.aspx

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

相关文章

php网站压测(ab)

一般来说核心页面都需要进行压测&#xff0c;特别是秒杀页面&#xff0c;从而知道网站的承受能力&#xff0c;方便暴露一些问题&#xff0c;更好的把控网站。压测工具有很多种&#xff0c;最简单、方便的可以使用ApacheBench&#xff0c;也就是我们熟悉的ab工具&#xff0c;不过…

在构建社交网站中,MySQL 和 MongoDB优缺点大比拼

在项目的规划和发展过程中&#xff0c;最关键的一步是要选择合适的数据库。如果选择错误的话&#xff0c;将会花费你大量时间和金钱&#xff0c;并且在这过程中还会惹毛很多的客户。当在他们预期方式中使用时&#xff0c;MongoDB和MySQL都是非常优秀的数据库&#xff0c;但究竟…

大型网站架构演化历程

大型网站的挑战主要来自庞大的用户&#xff0c;高并发的访问和海量数据&#xff0c;任何简单的业务一旦需要处理数以P计的数据和面对数以亿计的用户&#xff0c;问题就会变得棘手。大型网站架构主要就是解决这类问题。 本文内容大部分来自《大型网站技术架构》,这本书很值得一看…

强烈推荐几个比较好的Java代码查询网站

这些是我经常使用的一些Java代码查询网站&#xff0c;希望在这里能起到抛砖引玉的效果&#xff0c;大家群策群力&#xff0c;一起分享Java快乐。 1. java2s http://www.java2s.com/ 这个网站非常好&#xff0c;分成三大类&#xff0c;分别是 Example、 Products、 Articles&a…

今天在做网站中..........

程序员协会的网站已经拖了半年了&#xff0c;呵呵&#xff0c;一直想做 在听蓝色生死恋&#xff0c;嗯嗯&#xff0c;过去只是在街上听过&#xff0c;昨天晚上到Baidu找了半天&#xff0c;上传上来&#xff0c;大家共享一下&#xff01; 心情不咋样&#xff0c;早上抓了几个学…

如何用初级的JavaWeb知识写一个较简单的网站(一)

本人JavaWeb初学者&#xff0c;这是学校一门课程的期末作业&#xff0c;之前已经写了不少了&#xff0c;但是由于一点误操作&#xff0c;导致项目有点崩盘&#xff0c;加上心态不是很好&#xff0c;所以把整个项目全部删除重做&#xff0c;这里记录一下我写整个项目的全过程。 …

如何用初级的JavaWeb知识写一个较简单的网站(二)

好了&#xff0c;废话不多说&#xff0c;我们接着上次的项目继续开发 我们现在先暂时开发用户登录注册界面&#xff0c;上次我们已经完成了项目的初期准备&#xff0c;完成了建表、User实体类和UserDao的书写&#xff0c;下面我们开始套页 这里的前台页面是由一名前端程序员写…

影响网站打开速度的9大因素

再好的网站&#xff0c;如果打开速度慢&#xff0c;10个人会有9个人选择离开&#xff0c;我归纳了大约9大影响网站打开速度的因素&#xff0c;但网站页面显示的速度取决于众多的因素&#xff0c;包括服务器性能、网络传输质量、网站的带宽、DNS解析、网页内容包括涉及到的JS代码…

提高网站打开速度的7大秘籍

很多站长使用虚拟主机来做网站&#xff0c;网页内容一旦很多&#xff0c;网站打开速度就会特别慢&#xff0c;如果说服务器、带宽、CDN这类硬指标我们没有经济实力去做&#xff0c;不妨通过网页代码优化的方式来提高速度&#xff0c;卢松松总结了一些可行性的方法。 1: 缩小Jav…

12个在线网站测速工具——web性能

网站的访问速度对于一个网站非常重要&#xff0c;没有一个人会喜欢速度慢的网站。下面是12款在线测试网站的访问速度和性能的工具&#xff0c;在优化网站的时候很有用。 Pingdom 测试网站每个元素的加载速度&#xff0c;比如html、图片、JS文件等等。 GTmetrix GTmetrix集合…

谷歌搜索将衡量网站速度

据国外媒体报道&#xff0c;Google搜索结果排名将考量网页加载速度因素&#xff0c;网页加载速度慢的网站的Google搜索结果排名很可能会下滑。 Google的两位首席搜索工程师阿米特‧辛格哈尔&#xff08;Amit Singhal&#xff09;和马特•卡茨&#xff08;Matt Cutts&#xff09…

怎样让网站的文章(内页)快速收录和发外链的方法

做网站的站长们都知道&#xff0c;网站的文章的收录数量往往决定着网站的权重和网站的排名&#xff0c;所以一些站长对于网站的索引量看的极其重要。而最让人头疼的是&#xff0c;有时候当你费尽心思的写出一篇高质量的原创文章发表到网站以后&#xff0c;却迟迟不被收录&#…

windows server服务器上部署java+tomcat网站域名配置

windows server服务器上部署javatomcat网站域名配置 如果只是部署java项目的话&#xff0c;可以把IIS删除&#xff0c;然后在服务器上安装jdk tomcat 配置好环境变量&#xff0c;就和你在自己计算机上开发一样&#xff0c;把你的项目war包拷到tomcat下的webapps里&#xff08;…

python使用selenium爬取网站流程 适用于抓取使用了js等异步加载技术的网站

Python使用urllib.open再配合BeautifulSoup解析是最快的网页抓取方式&#xff0c;但部分网站做了反爬&#xff0c;用这种抓取方法会出错&#xff0c;就是浏览器里看网页内容是有的&#xff0c;但Python里抓出来的是空架子无数据。这种时候可以F12观察网站是否有直接的数据接口返…

应用程序和网站中创建几乎任何类型的工业条码控件BarcodeX.NET

BarcodeX.NET条形码控件是一种.NET WinForms组件和ASP.NET服务器控件&#xff0c;它可以在您的应用程序和网站中创建几乎任何类型的工业条形码。 具体功能&#xff1a; 100% C#托管代码适用于.NET框架2.0&#xff0c;3.0和3.5支持的条码包括&#xff1a;DataMatrix, PDF-417, …

轻量级设计,让网站灵敏轻便的6个技巧

在网站或软件的策划和设计过程中&#xff0c;我们经常听到这样的讨论&#xff1a;“这个功能设计得太重了”又或“我们希望能够处理得轻一些”。似乎轻设计是时下炙手可热的话题&#xff0c;也是方兴未艾的Web2.0大浪下设计师们的最爱&#xff08;看看那些在全世界遍地开花的SN…

做网站用UTF-8还是GB2312?

经常我们打开外国网站的时候出现乱码&#xff0c;又或者打开很多非英语的外国网站的时候&#xff0c;显示的都是口口口口口的字符&#xff0c; WordPress程序是用的UTF-8&#xff0c;很多cms用的是GB2312。 ● 为什么有这么多编码&#xff1f; ● UTF-8和GB2312有什么区别&…

如何查询几年的网站历史排名变化

在做网站之前&#xff0c; 我们要有一个明确的市场群体的定位&#xff0c;了解用户群体和竞争者。首先要查询竞争者网站排名的变化情况&#xff0c; 最好是几年的排名变化情况&#xff0c; 时间越长越能看出该类型的网站在市场的占有率和需求的稳定性。 那么如何知道 同类竞争者…