2.python web框架tornodo之正则路由、分页

一、自定义分页1
1.start.py文件代码如下:
import tornado.web
import tornado.ioloop
from controllers import home


settings = {
    "template_path": "views",
    "static_path": "statics",
}


app = tornado.web.Application([
    #基本路由
    (r"/index/(?P<page>\d*)", home.IndexHandler),
], **settings)


if __name__ == "__main__":
    app.listen(8090)
    tornado.ioloop.IOLoop.instance().start()
View Code

2.controllers文件夹下home.py文件代码如下:

import tornado.web
import tornado.ioloop


LIST_INFO=[
    {"userName":"test","email":"rrewqw"},
    ]

class IndexHandler(tornado.web.RequestHandler):
        # 每页显示5条,page表示是当前页
        # 第一页是0:5 ,第二页是5:10
        # start: (page-1)*5
        # end:page*5
    def get(self,page):
        #传过来page参数是字符串类型,需要转换成int类型
        try:
            page = int(page)
        except:
            #转换不成功返回第一页
            page = 1
        #page小于1的时候返回第一页
        if page<1:
            page=1
        #page大于总长度时返回第一页
        if page> len(LIST_INFO):
            page=1
        start = (page-1)*5
        end = page*5
        current_list=LIST_INFO[start:end]
        #返回分页的数据
        self.render("home/index.html",list_info=current_list)


    def post(self,*args,**kwargs):
        user=self.get_argument("userName")
        email=self.get_argument("email")
        temp={"userName":user,"email":email}
        LIST_INFO.append(temp)
        #重新跳转到index路由页面下,路由后面要加上/1,因为get方法有接收page参数
        self.redirect("/index/1")
View Code

3.views文件夹下home文件夹下index.html文件代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1>提交数据</h1>
  <!--提交数据到index/1路由下  -->
  <form action="/index/1" method="post">
      <input type="text" name="userName">
      <input type="text" name="email">
      <input type="submit" value="提交">
  </form>
  <h1>显示数据</h1>
  <table border="1">
      <thead>
        <tr>
            <th>用户名</th>
            <th>邮箱</th>
        </tr>
      </thead>
      <tbody>
            <!-- 接收list_info参数,循环遍历list_info,表格显示list_info中的userName和email  -->
            {% for item in list_info %}
                <tr>
                    <td>{{item['userName']}}</td>
                    <td>{{item['email']}}</td>
                </tr>
            {%end%}
      </tbody>
  </table>
</body>
</html>
View Code

4.运行start.py文件,浏览器中输入http://127.0.0.1:8090/index/1,返回index.html页面的第一页内容,页面输入userName或email提交数据到index/1路由下post方法下,post方法中获取提交的参数userName和email,并添加到LIST_INFO中后跳转index/1路由下index页面第一内容;浏览器中输入http://127.0.0.1:8090/index/2返回index.html页面的第二页内容

文件代码目录结构:

二、自定义分页2
上述代码http://127.0.0.1:8090/index/1或2页面添加数据后都是跳转到第一页,而应该在哪天添加就停留在哪一页,优化这一改动需要修改一下home.py文件post方法接收page参数,数据提交后跳转到index/page对应的页面,然后还需要修改get方法中render方法返回page参数,最后修改index.html文件中form标准中action

 1.controllers文件夹下home.py文件代码如下:

import tornado.web
import tornado.ioloop


LIST_INFO=[
    {"userName":"test","email":"rrewqw"},
    ]

class IndexHandler(tornado.web.RequestHandler):
        # 每页显示5条,page表示是当前页
        # 第一页是0:5 ,第二页是5:10
        # start: (page-1)*5
        # end:page*5
    def get(self,page):
        #传过来page参数是字符串类型,需要转换成int类型
        try:
            page = int(page)
        except:
            #转换不成功返回第一页
            page = 1
        #page小于1的时候返回第一页
        if page<1:
            page=1
        #page大于总长度时返回第一页
        if page> len(LIST_INFO):
            page=1
        start = (page-1)*5
        end = page*5
        current_list=LIST_INFO[start:end]
        #返回分页的数据
        self.render("home/index.html",list_info=current_list,current_page=page)


    def post(self,page):
        user=self.get_argument("userName")
        email=self.get_argument("email")
        temp={"userName":user,"email":email}
        LIST_INFO.append(temp)
        #重新跳转到index路由页面下,路由后面要加上/1,因为get方法有接收page参数
        self.redirect("/index/"+page)
View Code

2.views文件夹下home文件夹下index.html文件代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1>提交数据</h1>
  <!--提交数据到index/1路由下  -->
  <form action="/index/{{current_page}}" method="post">
      <input type="text" name="userName">
      <input type="text" name="email">
      <input type="submit" value="提交">
  </form>
  <h1>显示数据</h1>
  <table border="1">
      <thead>
        <tr>
            <th>用户名</th>
            <th>邮箱</th>
        </tr>
      </thead>
      <tbody>
            <!-- 接收list_info参数,循环遍历list_info,表格显示list_info中的userName和email  -->
            {% for item in list_info %}
                <tr>
                    <td>{{item['userName']}}</td>
                    <td>{{item['email']}}</td>
                </tr>
            {%end%}
      </tbody>
  </table>
</body>
</html>
View Code
3.运行start.py文件,浏览器中输入http://127.0.0.1:8090/index/1 ,添加数据大于5条后,再输入http://127.0.0.1:8090:/index/2页面添加数据都是停留在第二页
 
扩展:xss跨站脚本攻击
xss跨站脚本攻击,tronado框架模板语言默认给我们做防止xss跨站脚本攻击;如果我们tornado没有做防止跨站脚本攻击,在http://127.0.0.1:8090/index/1路由的index页面用户名输入框中输入<script>alert(123)</script>会跳窗提示一下,后面每次添加都会alert弹窗一下,而通过script中javascript可以document.getDocumentElementById获取我们用户名,也可以通过ajax获取我们的cookie进行伪造从而进行跨站脚本攻击。在tornado框架模板语言中通过{% raw {{arg}}%},表示接收原始输入内容
 
views文件夹下home文件夹下index.html文件代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1>提交数据</h1>
  <!--提交数据到index/1路由下  -->
  <form action="/index/1" method="post">
      <input type="text" name="userName">
      <input type="text" name="email">
      <input type="submit" value="提交">
  </form>
  <h1>显示数据</h1>
  <table border="1">
      <thead>
        <tr>
            <th>用户名</th>
            <th>邮箱</th>
        </tr>
      </thead>
      <tbody>
            <!-- 接收list_info参数,循环遍历list_info,表格显示list_info中的userName和email  -->
            {% for item in list_info %}
                <tr>
                    <td>{% raw item['userName'] %}</td>
                    <td>{{item['email']}}</td>
                </tr>
            {%end%}
      </tbody>
  </table>
</body>
</html>
View Code
 
三、自定义分页3
上述代码中每页只显示5条数据,当数据比较多的时候我们只能通过在浏览器中输入page参数进行查看数据,无法进行分页展示
1.controllers文件夹下home.py文件代码如下:
import tornado.web
import tornado.ioloop


LIST_INFO=[
    {"userName":"test","email":"rrewqw"},
    ]

for i in range(400):
    LIST_INFO.append({"userName":"sfa"+str(i),"email":"sfs%d"%(i)+"@163.com"})

class IndexHandler(tornado.web.RequestHandler):
        # 每页显示5条,page表示是当前页
        # 第一页是0:5 ,第二页是5:10
        # start: (page-1)*5
        # end:page*5
    def get(self,page):
        #传过来page参数是字符串类型,需要转换成int类型
        try:
            page = int(page)
        except:
            #转换不成功返回第一页
            page = 1
        #page小于1的时候返回第一页
        if page<1:
            page=1
        #page大于总长度时返回第一页
        if page> len(LIST_INFO):
            page=1
        start = (page-1)*5
        end = page*5
        current_list=LIST_INFO[start:end]
        #根据数据总数计算出总页码数和剩余条数
        all_page,c=divmod(len(LIST_INFO),5)
            if c>0:
                all_page+=1
        list_yema=[]
        #循环页面总数生成总页码数字符串并加入到页码列表中
        for num in range(all_page):
            str_page="<a href='/index/%s'>%s</a>"%(num+1,num+1)
            list_yema.append(str_page)
        yeMa="".join(list_yema)
                #返回分页的数据及总页码
        self.render("home/index.html",list_info=current_list, current_page=page,yeMa=yeMa)
        

    def post(self,page):
        user=self.get_argument("userName")
        email=self.get_argument("email")
        temp={"userName":user,"email":email}
        LIST_INFO.append(temp)
        #重新跳转到index路由页面下,路由后面要加上/1,因为get方法有接收page参数
        self.redirect("/index/"+page)

2.views文件夹下home文件夹下index.html文件代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pub{
            display: inline-block;
            overflow: auto;
        }
        .pub a{
            background-color: aquamarine;
            color: crimson;
            padding: 3px;
            margin: 3px;
        }
    </style>
</head>
<body>
  <h1>提交数据</h1>
  <!--提交数据到index/1路由下  -->
  <form action="/index/{{current_page}}" method="post">
      <input type="text" name="userName">
      <input type="text" name="email">
      <input type="submit" value="提交">
  </form>
  <h1>显示数据</h1>
  <table border="1">
      <thead>
        <tr>
            <th>用户名</th>
            <th>邮箱</th>
        </tr>
      </thead>
      <tbody>
            <!-- 接收list_info参数,循环遍历list_info,表格显示list_info中的userName和email  -->
            {% for item in list_info %}
                <tr>
                   <td>{{item['userName']}}</td>
                    <td>{{item['email']}}</td>
                </tr>
            {%end%}
      </tbody>
  </table>
  <div class="pub">
      {% raw yeMa %}
  </div>
</body>
</html>
View Code

3.运行start.py文件后,在浏览器中输入http://127.0.0.1:8090/index/1我们看到页面显示所有的页面

4.然后我们再把当前页面的页面样式进行高亮显示,controllers文件夹下home.py文件代码如下::

import tornado.web
import tornado.ioloop


LIST_INFO=[
    {"userName":"test","email":"rrewqw"},
    ]

for i in range(400):
    LIST_INFO.append({"userName":"sfa"+str(i),"email":"sfs%d"%(i)+"@163.com"})

class IndexHandler(tornado.web.RequestHandler):
        # 每页显示5条,page表示是当前页
        # 第一页是0:5 ,第二页是5:10
        # start: (page-1)*5
        # end:page*5
    def get(self,page):
        #传过来page参数是字符串类型,需要转换成int类型
        try:
            page = int(page)
        except:
            #转换不成功返回第一页
            page = 1
        #page小于1的时候返回第一页
        if page<1:
            page=1
        #page大于总长度时返回第一页
        if page> len(LIST_INFO):
            page=1
        start = (page-1)*5
        end = page*5
        current_list=LIST_INFO[start:end]
        #根据数据总数计算出总页码数和剩余条数
        all_page,c=divmod(len(LIST_INFO),5)
            if c>0:
                all_page+=1
        list_yema=[]
        #循环页面总数生成总页码数字符串并加入到页码列表中
        for num in range(all_page):
            if num+1==page:
                str_page="<a class='active' href='/index/%s'>%s</a>"%(num+1,num+1)
            else:
                str_page="<a href='/index/%s'>%s</a>"%(num+1,num+1)
            list_yema.append(str_page)
        yeMa="".join(list_yema)
                #返回分页的数据及总页码
        self.render("home/index.html",list_info=current_list, current_page=page,yeMa=yeMa)
        

    def post(self,page):
        user=self.get_argument("userName")
        email=self.get_argument("email")
        temp={"userName":user,"email":email}
        LIST_INFO.append(temp)
        #重新跳转到index路由页面下,路由后面要加上/1,因为get方法有接收page参数
        self.redirect("/index/"+page)
View Code

5.views文件夹下home文件夹下index.html文件代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pub{
            display: inline-block;
            overflow: auto;
        }
        .pub a{
            background-color: aquamarine;
            color: crimson;
            padding: 3px;
            margin: 3px;
        }
        .pub a.active{
            background-color: green;
            color: red;
            font-size: medium;
        }
    </style>
</head>
<body>
  <h1>提交数据</h1>
  <!--提交数据到index/1路由下  -->
  <form action="/index/{{current_page}}" method="post">
      <input type="text" name="userName">
      <input type="text" name="email">
      <input type="submit" value="提交">
  </form>
  <h1>显示数据</h1>
  <table border="1">
      <thead>
        <tr>
            <th>用户名</th>
            <th>邮箱</th>
        </tr>
      </thead>
      <tbody>
            <!-- 接收list_info参数,循环遍历list_info,表格显示list_info中的userName和email  -->
            {% for item in list_info %}
                <tr>
<!--                    <td>{{item['userName']}}</td>-->
                    <td>{% raw item["userName"]%}</td>
                    <td>{{item['email']}}</td>
                </tr>
            {%end%}
      </tbody>
  </table>
  <div class="pub">
      {% raw yeMa %}
  </div>
</body>
</html>
View Code

6.运行start.py文件后,在浏览器中输入http://127.0.0.1:8090/index/1我们看到页面的当前页会高亮显示

四、自定义分页4
上述代码中我们页面显示的所有的页码,这样页面不会好看,也未真正意义上实现分页,我们希望每页显示总页码为10个
1.controllers文件夹下home.py文件代码如下:
import tornado.web
import tornado.ioloop


LIST_INFO=[
    {"userName":"test","email":"rrewqw"},
    ]

for i in range(400):
    LIST_INFO.append({"userName":"sfa"+str(i),"email":"sfs%d"%(i)+"@163.com"})

class IndexHandler(tornado.web.RequestHandler):
        # 每页显示5条,page表示是当前页
        # 第一页是0:5 ,第二页是5:10
        # start: (page-1)*5
        # end:page*5
    def get(self,page):
        #传过来page参数是字符串类型,需要转换成int类型
        try:
            page = int(page)
        except:
            #转换不成功返回第一页
            page = 1
        #page小于1的时候返回第一页
        if page<1:
            page=1
        #page大于总长度时返回第一页
        if page> len(LIST_INFO):
            page=1
        start = (page-1)*5
        end = page*5
        current_list=LIST_INFO[start:end]
        #根据数据总数计算出总页码数和剩余条数
        all_page,c=divmod(len(LIST_INFO),5)
            if c>0:
                all_page+=1

        # 总页码数、当前页,每页10条数据;
        # 当总页码数《=11时显示总页码数,页码数范围是1,总页码数
        # 当总页码数》11时:
        #    如果当前页<=6,页码数范围是1,11
        #    如果当前页>6:
        #       如果当前+5>总页数,页码范围是总页码数-11,总页码数
        #       否则的话页码范围是当前页码数-5,当前页面数+5
        if all_page<11:
            s=1
            e=all_page
        else:
            if page<=6:
                s=1
                e=11
            else:
                if page+5>all_page:
                    s=all_page-10
                    e=all_page
                else:
                    s=page-5
                    e=page+5
        list_yema=[]
        #循环页面总数生成总页码数字符串并加入到页码列表中
        for num in range(s,e+1):
            if num==page:
                str_page="<a class='active' href='/index/%s'>%s</a>"%(num,num)
            else:
                str_page="<a href='/index/%s'>%s</a>"%(num,num)
            list_yema.append(str_page)
        yeMa="".join(list_yema)
                #返回分页的数据及总页码
        self.render("home/index.html",list_info=current_list, current_page=page,yeMa=yeMa)
        

    def post(self,page):
        user=self.get_argument("userName")
        email=self.get_argument("email")
        temp={"userName":user,"email":email}
        LIST_INFO.append(temp)
        #重新跳转到index路由页面下,路由后面要加上/1,因为get方法有接收page参数
        self.redirect("/index/"+page)
View Code

2.运行start.py文件后,在浏览器中输入http://127.0.0.1:8090/index/1我们看到页面正常进行了分页

 

五、自定义分页5
上述代码中我们的分页代码可以进行模块话,封装到一个分页的类中,后续我们用到分页的功能时都可以直接引用该分页代码
1.controllers文件夹下创建fenYe.py文件进行封装分页的功能
class fenYeModule:
    #需要接收一个数据总条数,当前页
    def __init__(self,LIST_INFO,current_page,numbers):
        try:
            current_page = int(current_page)
        except:
            current_page = 1
        if current_page<1:
            current_page=1
        self.current_page=current_page
        self.numbers=numbers
        #根据总条数进行计算分页的条数
        all_page,c=divmod(len(LIST_INFO),self.numbers)
        if c>0:
            all_page+=1
        self.all_page=all_page


    #定义每页展示数据条数
    def returnPageNum(self,LIST_INFO):
        start = (self.current_page-1)*self.numbers
        end = self.current_page*self.numbers
        current_list=LIST_INFO[start:end]
        return current_list


    def returnPageCode(self,base_url):
        # 总页码数、当前页,每页10条数据;
        # 当总页码数《=11时显示总页码数,页码数范围是1,总页码数
        # 当总页码数》11时:
        #    如果当前页<=6,页码数范围是1,11
        #    如果当前页>6:
        #       如果当前+5>总页数,页码范围是总页码数-11,总页码数
        #       否则的话页码范围是当前页码数-5,当前页面数+5
        if self.all_page<11:
            s=1
            e=self.all_page
        else:
            if self.current_page<=6:
                s=1
                e=11
            else:
                if self.current_page+5>self.all_page:
                    s=self.all_page-10
                    e=self.all_page
                else:
                    s=self.current_page-5
                    e=self.current_page+5
            #生成总页码
        list_yema=[]
        for num in range(s,e+1):
            if num==self.current_page:
                str_page="<a class='active' href='/%s%s'>%s</a>"%(base_url,num,num)
            else:
                str_page="<a href='/%s%s'>%s</a>"%(base_url,num,num)
            list_yema.append(str_page)
        yeMa="".join(list_yema)
        return yeMa

2.controllers文件夹下home.py文件代码如下:

import tornado.web
import tornado.ioloop
import fenYe#导入封装分页的模块,需要加入到python类库中,不然会找不到


LIST_INFO=[
    {"userName":"test","email":"rrewqw"},
    ]
for i in range(150):
    LIST_INFO.append({"userName":"sfa"+str(i),"email":"sfs%d"%(i)+"@163.com"})

class IndexHandler(tornado.web.RequestHandler):
    def get(self,page):
         obj=fenYe.fenYeModule(LIST_INFO,page,10)
        current_list=obj.returnPageNum(LIST_INFO)
        yeMa=obj.returnPageCode("index/")
        self.render("home/index.html",list_info=current_list, current_page=page,yeMa=yeMa)


    def post(self, page):
        user=self.get_argument("userName")
        email=self.get_argument("email")
        temp={"userName":user,"email":email}
        LIST_INFO.append(temp)
        self.redirect("/index/"+page)

3.运行start.py文件后,在浏览器中输入http://127.0.0.1:8090/index/1我们看到页面正常进行了分页

六.分页自定义5
上面的分页功能还不是很完善,我们希望显示首页、上一页、下一页、尾页以及输入数字进行跳转到指定页,下面来实现一下这个功能
1.controllers文件下fenYe.py文件代码如下:
class fenYeModule:
    #需要接收一个数据总条数,当前页
    def __init__(self,LIST_INFO,current_page,numbers):
        try:
            current_page = int(current_page)
        except:
            current_page = 1
        if current_page<1:
            current_page=1
        self.current_page=current_page
        self.numbers=numbers
        #根据总条数进行计算分页的条数
        all_page,c=divmod(len(LIST_INFO),self.numbers)
        if c>0:
            all_page+=1
        self.all_page=all_page


    #定义每页展示数据条数
    def returnPageNum(self,LIST_INFO):
        start = (self.current_page-1)*self.numbers
        end = self.current_page*self.numbers
        current_list=LIST_INFO[start:end]
        return current_list


    def returnPageCode(self,base_url):
        # 总页码数、当前页,每页10条数据;
        # 当总页码数《=11时显示总页码数,页码数范围是1,总页码数
        # 当总页码数》11时:
        #    如果当前页>=6,页码数范围是1,11
        #    如果当前页>6:
        #       如果当前+5>总页数,页码范围是总页码数-11,总页码数
        #       否则的话页码范围是当前页码数-5,当前页面数+5
        list_yema=[]
        #首页
        first_page="<a href='/%s1'>首页</a>"%(base_url)
        list_yema.append(first_page)
        #上一页
        if self.current_page==1:
            prev="<a href='javascript:void(0)'>上一页</a>"
        else:
            prev="<a href='/%s%s'>上一页</a>"%(base_url,self.current_page-1)
        list_yema.append(prev)


        if self.all_page<11:
            s=1
            e=self.all_page
        else:
            if self.current_page<=6:
                s=1
                e=11
            else:
                if self.current_page+5>self.all_page:
                    s=self.all_page-10
                    e=self.all_page
                else:
                    s=self.current_page-5
                    e=self.current_page+5


        for num in range(s,e+1):
            if num==self.current_page:
                str_page="<a class='active' href='/%s%s'>%s</a>"%(base_url,num,num)
            else:
                str_page="<a href='/%s%s'>%s</a>"%(base_url,num,num)
            list_yema.append(str_page)

        #下一页
        if self.current_page>=self.all_page:
            next_page="<a href='javascript:void(0)'>下一页</a>"
        else:
            next_page="<a href='/%s%s'>下一页</a>"%(base_url,self.current_page+1)
        list_yema.append(next_page)


        #尾页
        str_page="<a href='/%s%s' id='i1'>尾页</a>"%(base_url,self.all_page)
        list_yema.append(str_page)


        #跳转指定页
        input_page="<input type='text'> <a onclick=jump('%s',this)>go</a>"%(base_url)
        
        script=""" <script>
            function jump(base_url,self){
                var page=self.previousElementSibling.value;
                if(page.trim().length>0){
                    location.href=page;
                }
            }
        </script>"""
        list_yema.append(input_page)
        list_yema.append(script)


        yeMa="".join(list_yema)
        return yeMa
View Code

2.运行start.py文件后,在浏览器中输入http://127.0.0.1:8090/index/1我们看到页面正常进行了分页

 

 以上至此分页功能就已经全部完善完成,完整代码目录结构如下:

 

 

posted @ 2023-04-06 06:11  少壮不努力123  阅读(134)  评论(0)    收藏  举报