Crossin的编程教室

标题: Python 实战(1):在网页上显示信息 [打印本页]

作者: crossin先生    时间: 2015-4-6 20:32
标题: Python 实战(1):在网页上显示信息
someweb-01.png

上次简单介绍了 web.py。今天先来粗略解释下那个 hello world 页面的代码:

import web

导入 web.py 模块。

urls = (
   '/', 'index'
)

这是指定网站 url 的匹配规则,左边是正则表达式,右边是对应处理函数的名称。

class index:
   def GET(self):
       return "Hello, world!"

这便是处理请求的函数 index。GET 和 POST 是 HTTP 的两种请求方式,一般来说,GET 用于请求网页,而 POST 多用于提交表单。举个不严谨的栗子:当你在浏览器地址栏中输入一个地址并按下回车,就是发送了一个 GET 请求;而当你在打开的页面中输入用户名和密码,点击登录按钮,则是发送了一个 POST 请求。这里的 GET 函数描述了对于一个 GET 请求的处理方式:直接返回一个字符串。

if __name__ == "__main__":
   app = web.application(urls, globals())
   app.run()

最后,当这个代码文件被执行时,我们将创建一个 application,它会按照我们定义的 url 规则进行对应的处理,并在后台一直运行,独自等待请求的到来。

插一句:由于这个系列的文章侧重于“实战”,所以我只会搬开挡在道路正前方的石头,对于涉及的诸多细节无法面面俱到。即使这段简单的 hello world 代码中,关于 url 的正则匹配、GET / POST 的区别等,都可说上很多。但现在我只能略过。如有疑问,欢迎在QQ群和论坛上讨论。

仅仅在页面上显示 hello world 显然不能满足我的需求。我是想要一个关于电影的网站,那最起码得在页面上显示一些电影的信息吧。

一种显而易见的方法是,把要显示的信息拼成字符串,然后返回。

在代码里定义一组数据,一个由 dict 组成的 list:

movies = [
        {
                'title': 'Forrest Gump',
                'year': 1994,
        },
        {
                'title': 'Titanic',
                'year':        1997,
        },

然后把 GET 方法改为:

def GET(self):
   page = ''
   for m in movies:
       page += '%s (%d)\n' % (m['title'], m['year'])
   return page

movies 是一个包含了影片标题和年代信息的 list。在 GET 方法中,把 movies 里每一条内容取出来,拼接成一整个字符串,作为结果返回。

如果你之前已经运行了 code.py,刷新页面将会看到新的内容:

Forrest Gump (1994)
Titanic (1997)

是不是有点类似在命令行输出结果或者在文本文件中存储内容?但作为一个网页,如果以后要添加更多的显示效果和交互功能,这样写肯定是要跪。好在 web.py 给我们提供了一种更方便的页面展示方式 -- 模板。

刚才我们用的方法类似于在 Python 里写 HTML,这是比较痛苦的。而 web.py 的模板是让你能在 HTML 里写 Python。

首先我们需要在代码里指定模板:

render = web.template.render('templates/')

在 GET 方法里调用模板:

def GET(self):
  return render.index()

模板的返回值就是一个处理好的页面,所以直接 return 就可以了。

然后在项目文件夹,也就是 code.py 所在的目录下新建一个叫做 templates 的目录,里面新建一个 index.html 文件作为模板。注意这里的 templates、index 命名都需要与你代码里的设定一致。如果你是吧一个 muban 文件夹下的 shouye.html 作为模板,那相应代码就应改为:

render = web.template.render('muban/')
render.shouye()

在模板 index.html 里写下:

<h1>Crossin's Movie Site</h1>

h1 是 HTML 中表示标题的标签。保存 code.py 和 index.html 后刷新页面,你将会看到一行很大的标题:

Crossin's Movie Site

这表示模板已经生效了。但 movies 的信息仍然没有显示。如果需要在模板中显示信息,需要将信息传递给模板:

def GET(self):
  return render.index(movies)

然后在模板里,接收并使用传递进来的参数:

$def with (movies)
<h1>Crossin's Movie Site</h1>
$movies

web.py 模板中的 $def with 表示这个模板中将要使用的变量。注意务必把它放在模板的第一行。如果有多个参数,需要全部依次列在括号中。

$movies 则表示获取 movies 变量的值。

保存刷新,页面上已经可以看到我们在代码中定义的 movies 信息了,但还是 list 直接转换字符串的效果。

更近一步地,我们可以在模板中对数据进行操作,让它们看起来更顺眼一点:

$for movie in movies:
        <li>
        $movie['title'], $movie['year']
        </li>

模板中的语法和 Python 类似,只是前面需要增加 $ 符号。缩进依然需要按照 Python 中的规范。li 是 HTML 中列表的标签。

这时候,页面上已经就能以列表的形式显示电影信息了(封面图所示)。尽管依然简陋,但一切才刚刚开始,我们的征途是星辰大海。


someweb-1-index.html (117 Bytes, 下载次数: 593)







someweb-1-code.py

382 Bytes, 下载次数: 559

code.py


作者: xinyewdz    时间: 2015-4-12 12:10
我现在使用的是Python3.3,但是web.py不支持3.3. 请问有什么其他的库可以代替的吗?或者其他的解决方法。
作者: crossin先生    时间: 2015-4-12 15:52
xinyewdz 发表于 2015-4-12 12:10
我现在使用的是Python3.3,但是web.py不支持3.3. 请问有什么其他的库可以代替的吗?或者其他的解决方法。 ...

试试这个版本吧 https://github.com/webpy/webpy/tree/python3
但不一定完全兼容
作者: YsGer    时间: 2015-5-19 06:20
支持一个  谢谢
作者: 艾傻傻    时间: 2015-5-28 00:21
<type 'exceptions.AttributeError'> at /
No template named index

Python        /Library/Python/2.7/site-packages/web.py-0.37-py2.7.egg/web/template.py in _load_template, line 1000
Web        GET http://0.0.0.0:8080/


这个是怎么回事?index.html 在templates目录下创建了的,最后copy了你的代码,还是不能显示Crossin's Movie Site
作者: crossin先生    时间: 2015-5-29 15:09
艾傻傻 发表于 2015-5-28 00:21
at /
No template named index

render = web.template.render('templates/')

不知道啊,你过一遍代码,看看里面路径设置是不是都正确
这个报错应该就是模板文件没找到
作者: 煞笔小七    时间: 2015-6-1 11:37
艾傻傻 发表于 2015-5-28 00:21
at /
No template named index

可能crossin没有说清楚。函数里必须带参数,在这里是
def GET(self):
  return render.index(movies)
并且要在模板里接收传递进来的参数
$def with (movies)
<h1>Crossin's Movie Site</h1>
然后才能显示出显示Crossin's Movie Site,Windows下是这样的情况,不知道Mac是不是
作者: guoguolgp    时间: 2015-6-17 16:57
请教如下问题:
我在模板文件中输入$for m in movies: 系统提示 take no arguments
如果输入的是
$def with(movies)
$movies
则通过,没有问题


作者: crossin先生    时间: 2015-6-18 18:51
guoguolgp 发表于 2015-6-17 16:57
请教如下问题:
我在模板文件中输入$for m in movies: 系统提示 take no arguments
如果输入的是

模板中使用传入的变量必须在第一行$def with
作者: hipeter    时间: 2015-11-16 20:01
guoguolgp 发表于 2015-6-17 16:57
请教如下问题:
我在模板文件中输入$for m in movies: 系统提示 take no arguments
如果输入的是

$for m in movies:
下面也要:
        <li>
        $m['title'],$m['year']
        </li>
作者: 雏菊    时间: 2016-3-6 12:15
麻烦问下,编辑html文件,输入代码是不是要用dreamweaver?
作者: 雏菊    时间: 2016-3-6 12:16
雏菊 发表于 2016-3-6 12:15
麻烦问下,编辑html文件,输入代码是不是要用dreamweaver?

问什么我都输入好了以后,打开地址出现这个:<type 'exceptions.UnicodeDecodeError'> at
'utf8' codec can't decode byte 0xce in position 7: invalid continuation byte

Python        C:\Python27\lib\encodings\utf_8.py in decode, line 15
Web        GET http://127.0.0.1:8080/

作者: crossin先生    时间: 2016-3-6 14:41
雏菊 发表于 2016-3-6 12:15
麻烦问下,编辑html文件,输入代码是不是要用dreamweaver?

不一定要用dw,其他编辑器也可以。
作者: crossin先生    时间: 2016-3-6 14:59
雏菊 发表于 2016-3-6 12:16
问什么我都输入好了以后,打开地址出现这个: at
'utf8' codec can't decode byte 0xce in position 7: i ...

字符编码有问题。但从你给的这点信息看不出是哪里的问题。你先把中文都换成英文来做,应该没问题。然后再找是哪里的中文出了问题。

另外也可能是你的编辑器保存文件时候用了带BOM的utf8的格式。如果可以设定的话,要选无BOM格式
作者: 雏菊    时间: 2016-3-6 17:45
crossin先生 发表于 2016-3-6 14:59
字符编码有问题。但从你给的这点信息看不出是哪里的问题。你先把中文都换成英文来做,应该没问题。然后再 ...

先生,这个把中文换成英文来做是什么意思?
作者: 雏菊    时间: 2016-3-6 18:33
哈哈哈啊哈!谢谢先生,虽然不知道为啥,但是运行起来了。。。。好激动!!!
作者: spritezhong    时间: 2016-3-18 10:57
艾傻傻 发表于 2015-5-28 00:21
at /
No template named index

我是在linux下写的代码,也遇到了这个问题,你的问题解决了吗?
作者: crossin先生    时间: 2016-3-18 13:12
spritezhong 发表于 2016-3-18 10:57
我是在linux下写的代码,也遇到了这个问题,你的问题解决了吗?

报错是因为程序找不到模板,但我不清楚问题原因。检查一下各个参数、路径是不是都正确
作者: tianqi2008    时间: 2016-4-12 11:45
雏菊 发表于 2016-3-6 12:16
问什么我都输入好了以后,打开地址出现这个: at
'utf8' codec can't decode byte 0xce in position 7: i ...

当时也出现这个错误,我当前路径带有中文,改回英文后就可以正常了
作者: lzlz    时间: 2016-12-20 11:23
crossin先生 发表于 2016-3-18 13:12
报错是因为程序找不到模板,但我不清楚问题原因。检查一下各个参数、路径是不是都正确 ...

我也遇到了这个问题,不知道什么原因,但是模板路径改成绝对路径就好了。
作者: 大侠小虾    时间: 2017-2-18 04:56
代码里错误很多啊

作者: crossin先生    时间: 2017-2-18 17:02
大侠小虾 发表于 2017-2-18 04:56
代码里错误很多啊

啥?
作者: nekonekobox    时间: 2017-2-22 00:25
if __name__ == "__main__":
   app = web.application(urls, globals())
   app.run()

关于上面这一段不太理解,查了下资料
if __name__ == "__main__"貌似是一个常用的固定用法
用来调试的?
当直接命令行调用code.py时,__name__ 会自动置为 "__main__",因此触发if条件
app = web.application(urls, globals())
app.run()
但是如果通过其他py文件调用code.py就不会触发if条件对吧?
这么做的原因时什么呢?为什么不能直接
app = web.application(urls, globals())
app.run()
作者: crossin先生    时间: 2017-2-22 15:49
nekonekobox 发表于 2017-2-22 00:25
if __name__ == "__main__":
   app = web.application(urls, globals())
   app.run()

如果你这个文件被其他文件 import,就不会运行这段代码。

单从目前这个例子来说,加不加无所谓
作者: 布拉格广场    时间: 2017-6-16 20:13
Traceback (most recent call last):
  File "D:\python\lib\site-packages\web.py-0.40.dev0-py3.6.egg\web\application.py", line 257, in process
    return self.handle()
  File "D:\python\lib\site-packages\web.py-0.40.dev0-py3.6.egg\web\application.py", line 248, in handle
    return self._delegate(fn, self.fvars, args)
  File "D:\python\lib\site-packages\web.py-0.40.dev0-py3.6.egg\web\application.py", line 487, in _delegate
    cls = fvars[f]
KeyError: 'index'

127.0.0.1:61127 - - [16/Jun/2017 20:01:54] "HTTP/1.1 GET /" - 500 Internal Server Error
127.0.0.1:61127 - - [16/Jun/2017 20:01:55] "HTTP/1.1 GET /favicon.ico" - 404 Not Found



这个问题是什么原因呢?

作者: crossin先生    时间: 2017-6-17 00:41
布拉格广场 发表于 2017-6-16 20:13
Traceback (most recent call last):
  File "D:\python\lib\site-packages\web.py-0.40.dev0-py3.6.egg\we ...

报错里写了
cls = fvars[f]
这句有问题。f的值是‘index’,但是没有这个键
作者: 13253620252    时间: 2017-11-15 15:44
先生,创建index.html是不是要用Python中的IDLE来写
作者: crossin先生    时间: 2017-11-15 19:32
13253620252 发表于 2017-11-15 15:44
先生,创建index.html是不是要用Python中的IDLE来写

都可以,不是必须
作者: Joseph丶Joe    时间: 2018-4-17 11:52
C:\Users\Administrator\Desktop/QQ图片20180417115054请问这样怎么解决
作者: crossin先生    时间: 2018-4-18 00:02
Joseph丶Joe 发表于 2018-4-17 11:52
请问这样怎么解决

点“高级模式”,图片,上传图片
作者: fionalailai    时间: 2020-3-17 23:15
为什么我一致code.py,结果中显示http://0.0.0.0:8080/之后整个IDLE就卡住了,每次都得强制关闭,重新打开再次执行又出现同样的问题
作者: crossin先生    时间: 2020-3-18 23:21
fionalailai 发表于 2020-3-17 23:15
为什么我一致code.py,结果中显示http://0.0.0.0:8080/之后整个IDLE就卡住了,每次都得强制关闭,重新打开 ...

从命令行里到代码所在目录下,通过 python code.py 启动。不要在idle里跑




欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5