Google App Engine(GAE)实现一个web收藏并实现简单的分页功能

本文介绍如何使用Google App Engine (GAE) 进行实体创建、数据添加与修改、数据选择展示及数据删除等操作,并提供了详细的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于什么是Google App Engine(GAE)以及初始开发环境的配置。已经有许多的先驱者介绍了,我也就不再画蛇添足了。

限于本人表达能力有限,我就以贴代码为主。附带少数说明

第一步:建立数据实体。
此处我建了两个实体。一个用来存放导航分类
一个用来存放具体的分类信息
下面是代码

 

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 #导航分类
 2 class NavType(db.Model):
 3     typeName = db.StringProperty()
 4     userEmail = db.StringProperty()
 5     dataCount = db.IntegerProperty()
 6 #具体导航信息
 7 class UserNav(db.Model):
 8     #登录者邮件地址
 9     userEmail = db.StringProperty()
10     #登录的分类KEY
11     navTypeKey = db.StringProperty()
12     #导航描述
13     navDes = db.StringProperty(multiline=True)
14     #导航标题
15     navName = db.StringProperty()
16     #导航链接
17     navLink = db.StringProperty()
18     #附加字段 排序查询用 本来想用时间做查询排序的可时间类型我不知道怎么转换就放弃了
19     navNumIndex = db.IntegerProperty()
20     #登录时间
21     navDate = db.DateTimeProperty(auto_now_add=True)

 

第二步:添加,修改数据。

 

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 navInfo = {}
 2 typeInfo = {}
 3 #这个值主要是分页时用
 4 navNumIndex = long(time.time())
 5 #前台页面传的值,新添加时为空
 6 navKey = self.request.get('navKey')
 7 
 8 navName = self.request.get('navName')
 9 navLink = self.request.get('navLink')
10 navDes = self.request.get('navDes')
11 navTypeName = self.request.get('navTypeName')            
12 navTypeKey = self.request.get('typeKey')
13 
14 #--------------取得导航实体------------------------------------------------------------------
15 if navKey:
16     navInfo = db.get(db.Key(navKey))
17 else:
18     navInfo = DB.UserNav()
19 
20 #--------------取得分类key----------------------------------
21 #这里标识一下是否需要新建一个分类
22 newTypeFlg = True
23 if navTypeKey:
24     typeInfo = db.get(db.Key(navTypeKey))
25     navTypeCount = 0
26     if typeInfo.typeName != navTypeName:
27         navTypeCount = typeInfo.dataCount -1
28         if navTypeCount>0:
29             typeInfo.dataCount = navTypeCount
30             typeInfo.put()
31         else:
32             db.delete(typeInfo)                    
33     else:
34         newTypeFlg = False
35 #根据名检索一下是否已经存在修改后或新输入的分类名
36 typeResult = db.GqlQuery("SELECT * FROM NavType WHERE typeName=:1 AND userEmail=:2",navTypeName,userEmail).fetch(1)                     
37 if len(typeResult) == 1:
38     typeObj = typeResult[0]
39     #增加此分类的条数
40     typeObj.dataCount=typeObj.dataCount+1
41     typeObj.put()
42     navTypeKey = str(typeObj.key())
43     newTypeFlg = False
44     
45 if newTypeFlg:
46     typeObj = DB.NavType()
47     typeObj.typeName = navTypeName
48     typeObj.userEmail = userEmail
49     #第一次添加时为1
50     typeObj.dataCount=1
51     typeObj.put()
52     navTypeKey = str(typeObj.key())
53 
54 navInfo.navTypeKey=navTypeKey
55 navInfo.navName=navName
56 navInfo.navLink=navLink
57 navInfo.navDes=navDes
58 navInfo.userEmail=userEmail
59 navInfo.navNumIndex = navNumIndex
60 navInfo.put()

 

第三步:选择,显示数据
这里用了JQuery的Ajax方法因此返回的是构建好的json格式。对于特殊字符也进行了转换。先发特殊字符转换函数,以便于理解。

 

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 def strReplace(str):
 2     #说明 |squot| 单引号;|dquot| 双引号; |colon| 冒号
 3     #|lbrace| |rbrace| 左右大括号; |lbracket| |rbracket| 左右中括号; |comma|逗号;
 4     # 以上为json语法符号 在最后需要原样转回
 5     replaceMap = {"<":"&lt;",">":"&gt;","{":"&#123;","}":"&#125;","[":"&#91;","]":"&#93;","(":"&#40;",")":"&#41;",
 6                   "\"":"&quot;","'":"&#39;",",":"&#44;",":":"&#58;",";":"&#59;","\r\n":"&nbsp;","\n":"&nbsp;"}
 7     returnMap = {"|squot|":"'","|dquot|":"\"","|colon|":":","|lbrace|":"{","|rbrace|":"}",
 8                  "|lbracket|":"[","|rbracket|":"]","|comma|":","}
 9     if str:
10         #这两个for语句有先后顺序
11         for key,val in replaceMap.items():
12             str = str.replace(key,val)
13         for key1,val1 in returnMap.items():
14             str = str.replace(key1,val1)
15     else:
16         str = ""
17     return str
18 def getNavTypeJson(typeObj):
19     #这里键值写 text value 是为了在前台与dropdownlist的选项统一 容易遍历
20     jsonStr = "|squot|text|squot||colon||squot|"+typeObj.typeName + "|squot||comma||squot|value|squot||colon||squot|"+str(typeObj.key())+"|squot|"
21     jsonStr += "|comma||squot|dataCount|squot||colon||squot|"+str(typeObj.dataCount)+"|squot|"
22     return jsonStr
23 def getNavListJson(navObj,showModel):
24     jsonStr = ""
25     #返回关键字及形式 'navName':'name','navLink':'link','navType':'typeKey','navKey':'navKey','navNumIndex':'navNumIndex','navDes':'description'
26     jsonStr = "|squot|navName|squot||colon||squot|"+navObj.navName + "|squot||comma||squot|navLink|squot||colon||squot|"+navObj.navLink
27     jsonStr += "|squot||comma||squot|navNumIndex|squot||colon||squot|"+str(navObj.navNumIndex)+ "|squot||comma||squot|navKey|squot||colon||squot|"+str(navObj.key())+"|squot|"
28     if showModel=='full':
29         jsonStr += "|comma||squot|navDes|squot||colon||squot|"+navObj.navDes+"|squot||comma||squot|navTypeKey|squot||colon||squot|"+navObj.navTypeKey + "|squot|"
30     
31     return jsonStr

 

下面是选取数据的代码

 

ContractedBlock.gif ExpandedBlockStart.gif Code
  1 navList = []
  2 navTypeList = []
  3 results = []
  4 typeJsonStr = '|lbracket||rbracket|'
  5 
  6 #前一页 后一页按钮的可用状态
  7 pageNext = False
  8 pagePre = False            
  9 
 10 #默认完整模式 一页10条数据
 11 pageSize = 10;
 12 
 13 
 14 #以简单模式还是完整模式查看
 15 showModel = self.request.get('showModel')
 16 if showModel == 'sample':
 17     pageSize = 100
 18 
 19 #分页数据取得时的index值
 20 pageKey = self.request.get('pageKey')
 21 #取上一页还是下一个数据
 22 pagingTo = self.request.get('pagingTo')
 23 #选择条件 分类key
 24 navTypeKey = self.request.get('typeKey')
 25 
 26 #页当前返回数据所在页号
 27 pageCountIndex = int(self.request.get('pageCountIndex'))
 28 
 29 whereStr = "WHERE userEmail = :1 "
 30 #当点击上一页或下一页按钮时
 31 if pageKey:
 32     if pagingTo == 'next':
 33         if pageCountIndex>pageSize:
 34             pageCountIndex = (pageCountIndex-1)/pageSize                    
 35             pageCountIndex += 1
 36         ##sys.__stdout__.write("wen"+str(pageCountIndex))
 37         if navTypeKey:
 38             whereStr = whereStr + " AND navNumIndex<:2 AND navTypeKey=:3 ORDER BY navNumIndex DESC"
 39             results = DB.UserNav.gql(whereStr,userInfo["email"],long(pageKey),navTypeKey).fetch(pageSize+1)
 40         else:
 41             whereStr = whereStr + " AND navNumIndex<:2 ORDER BY navNumIndex DESC"
 42             results = DB.UserNav.gql(whereStr,userInfo["email"],long(pageKey)).fetch(pageSize+1)
 43         navCount = len(results)
 44         #results的结果就是相对点击按钮时的下一页的数据
 45         #数据条数大于0说明有下一页的数据则上一页按钮就可用了
 46         if navCount > 0:
 47             pagePre = True
 48         #数据条数大于20说明有下下一页的数据则下一页按钮就可用了
 49         if navCount > pageSize:
 50             #删除最后一个元素
 51             results.pop()
 52             pageNext = True
 53     elif pagingTo == 'pre':
 54         if pageCountIndex>pageSize:
 55             pageCountIndex = (pageCountIndex-1)/pageSize                    
 56             pageCountIndex -= 1
 57         
 58         
 59         #这里用了一个等于号就是为了判断是否有上一页的数据
 60         if navTypeKey:
 61             whereStr = whereStr + " AND navNumIndex>:2 AND navTypeKey=:3 ORDER BY navNumIndex ASC"
 62             results = DB.UserNav.gql(whereStr,userInfo["email"],long(pageKey),navTypeKey).fetch(pageSize+1)
 63         else:
 64             whereStr = whereStr + " AND navNumIndex>:2 ORDER BY navNumIndex ASC"
 65             results = DB.UserNav.gql(whereStr,userInfo["email"],long(pageKey)).fetch(pageSize+1)                        
 66         
 67         navCount = len(results)
 68         #results的结果就是相对也点击按钮时的前一页的数据
 69         #数据条数大于0说明有上一页的数据则下一页按钮就可用了
 70         if navCount > 0:
 71             pageNext = True
 72         #数据条数大于pageSize说明有上上一页的数据则上一页按钮就可用了
 73         if navCount > pageSize:
 74             #删除最后一个元素
 75             results.pop()
 76             pagePre = True
 77         #此处是按升序查询的数据因此显示的时候需要在把数组反正一下
 78         results.reverse()
 79 #页面第一次运行或选择一个分类后
 80 else:
 81     #取某一个分类的所有信息
 82     if navTypeKey:
 83         results= DB.UserNav.gql(whereStr+" AND navTypeKey=:2 ORDER BY navNumIndex DESC",userInfo["email"],navTypeKey).fetch(pageSize+1)
 84     else:
 85         #第一次运行时取所有分类
 86         typeResults = DB.NavType.gql("WHERE userEmail = :1 ",userInfo["email"]).fetch(1000)
 87         
 88         for typeObj in typeResults:
 89             navTypeList.append(getNavTypeJson(typeObj))
 90             typeJsonStr = "|lbracket||lbrace|"+"|rbrace||comma||lbrace|".join(navTypeList)+"|rbrace||rbracket|"
 91         
 92         results= DB.UserNav.gql(whereStr+" ORDER BY navNumIndex DESC",userInfo["email"]).fetch(pageSize+1)
 93     
 94     #此处是页面第一次运行的时候,前一页按钮肯定不好用
 95     if len(results) >pageSize:
 96         pageNext = True
 97         #删除最后一个元素
 98         results.pop()
 99 pageCountIndex = (pageCountIndex*pageSize) + 1
100 retJsonStr += "|comma||squot|pageCountIndex|squot||colon||squot|"+str(pageCountIndex)+"|squot|"
101 retJsonStr += "|comma||squot|navTypes|squot||colon|"+typeJsonStr+"|comma||squot|pagePre|squot||colon||squot|"+str(pagePre)+"|squot|"
102 retJsonStr += "|comma||squot|pageNext|squot||colon||squot|"+str(pageNext)+"|squot||comma||squot|navList|squot||colon||lbracket|"
103 if len(results) > 0:
104     for nav in results:                    
105         navList.append(getNavListJson(nav,showModel))
106     retJsonStr += "|lbrace|"+"|rbrace||comma||lbrace|".join(navList)+"|rbrace|"
107 retJsonStr += "|rbracket|"
108 self.response.out.write(settings.strReplace("|lbrace|"+retJsonStr+"|rbrace|"))

 

第四步 数据删除,分类修改
首先是数据删除部分


 

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 
 2 #要删除数据的KEY,删除全部时此值为空
 3 navKey = self.request.get('navKey')
 4 typeKey = self.request.get('typeKey')
 5 if navKey:#删除一个            
 6     result = db.get(db.Key(navKey))
 7     db.delete(result)
 8     
 9     #取得所属分类
10     navType = db.get(db.Key(typeKey))
11     dataCount = navType.dataCount-1
12     if dataCount>0:
13         navType.dataCount = navType.dataCount-1;
14         navType.put()
15     else:
16         db.delete(navType)
17 else:#删除全部
18     #Google提供的查询最多返回1000条数据因此这里设定了一个循环删除数据
19     delNavFlg = True
20     while delNavFlg:
21         results = db.GqlQuery("SELECT * FROM UserNav WHERE userEmail = :1",userEmail).fetch(500)
22         if len(results) <1:
23             delNavFlg = False
24         db.delete(results)
25     #导航删除以后所有分类也删除
26     delTypeFlg = True
27     while delTypeFlg:
28         results = db.GqlQuery("SELECT * FROM NavType WHERE userEmail = :1",userEmail).fetch(500)
29         if len(results) <1:
30             delTypeFlg = False
31         db.delete(results)    

分类修改部分

 

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 typeKey = self.request.get('typeKey')
 2 typeName = self.request.get('typeName')
 3 result = db.get(db.Key(typeKey))
 4 if typeName:
 5     result.typeName=typeName
 6     result.put()
 7 else:
 8     db.delete(result)
 9     #删除当前分类包含的所有导航信息
10     delFlg = True
11     while delFlg:
12         results = db.GqlQuery("SELECT * FROM UserNav WHERE userEmail = :1 AND navTypeKey=:2",userEmail,typeKey).fetch(500)
13         if len(results) <1:
14             delFlg = False
15         db.delete(results)

 

对于GAE我是也就是刚刚看到其门槛的菜鸟,写这些只是希望能对刚刚接触的人提供一点参考。

完整的代码由于还包括其他的小应用,我就不主动拿出来丢人了。有需要参考一下的可以单独联系。
有想看实例的可以到http://daily-manage.appspot.com/这里看。我已经上传到Google的服务器上去了。

转载于:https://www.cnblogs.com/yuhun23/archive/2009/06/08/1498776.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值