《笨方法学Python》习题50

习题 50: 你的第一个网站

1. 安装lpthw.web

在创建网页应用程序之前,需要安装一个“Web框架”,叫做lpthw.web。
所谓“框架”,通常是指“让某件事情做起来更容易的软件包”。在网页应用的世界里,人们创建了各种各样的“网页框架”,用来解决他们在创建网站时遇到的问题,然后把这些解决方案用软件包的方式发布出来,这样你就可以利用它们引导创建你自己的项目了。

$ sudo pip install lpthw.web

注意⚠️:直接执行上述命令下载lpthw.web的可能会报以下错误:

Could not find a version that satisfies the requirement lpthw.web 

解决方案:

1. 下载[lpthw.web-1.1.tar.gz](https://files.pythonhosted.org/packages/52/0d/a200087bb551895143fedfb5f7df416ccb7ecb46428e04dd011a7ea19689/lpthw.web-1.1.tar.gz)
2. 解压,并将文件拷贝到pip的第三方库的安装目录,参考:/usr/local/lib/python2.7/site-packages(可以通过pip show nose命令查看)
3. cd进入到文件夹下,执行命令: $sudo python setup.py install

(PS:以上是 Linux 和 Mac OSX 系统下的安装命令)


2. 写一个简单的“Hello World”项目

现在你将作出一个非常简单的‘hello world’项目出来,首先需要创建一个项目目录:

$ cd projects
$ mkdir gothonweb
$ cd gothonweb
$ mkdir bin gothonweb tests docs templates
$ touch gothonweb/__init__.py
$ touch tests/__init__.py

将下面的代码放到app.py中:

import web

urls = (
    '/', 'index'
)
app = web.application(urls, globals())
class index(object):
    def GET(self):
        greeting = "Hello World"
        return greeting
if __name__ == "__main__":
    app.run()

使用下面的方法来运行这个web程序:

$ python bin/app.py

注意⚠️:如果出现下方这种提示,说明8080端口被占用(后来发现是Nginx占用了8080端口,关掉Nginx就好了):

no socket could be created

如果没有出现问题,就会出现下面的提示:

http://0.0.0.0:8080/
127.0.0.1:50947 - - [16/Apr/2019 19:28:31] "HTTP/1.1 GET /" - 200 OK

这些是lpthw.web打印出的 log 信息,从这些信息你可以看出服务器有在运行。

发生了什么事情?

在浏览器访问到你的网页应用程序时,发生了下面一些事情:

  1. 浏览器通过网络连接连接到你自己的电脑,它的名字叫做localhost,这是一个标准称谓,表示的谁就是网络中你自己的这台计算机,不管它实际名字是什么,你都可以使用localhost来访问。它使用的网络端口是5000。
  2. 连接成功以后,浏览器对bin/app.py这个应用程序发出了HTTP请求(request),要求访问URL/,这通常是一个网站的第一个URL。
  3. 在bin/app.py里,我们有一个列表,里面包含了URL和类的匹配关系。我们这里只定义了一组匹配,那就是‘/’,‘index’的匹配。他的含义是:如果有人使用浏览器访问/这一级目录,lpthw.web将找到并加载class index,从而用它处理这个浏览器请求。
  4. 现在lpthw.web找到了class index,然后针对这个类的一个实例调用了index.GET这个方法函数。该函数运行后返回一个字符串,以供lpthw.web将其传递给浏览器。
  5. 最后lpthw.web完成了对于浏览器请求的处理,将相应回传给浏览器,于是你就看到了现在的页面。

修正错误

第一步,把第 11 行的greeting变量赋值删掉,然后刷新浏览器。你应该会看 到一个错误页面,你可以通过这一页丰富的错误信息看出你的程序崩溃的原因是 什么。当然你已经知道出错的原因是 greeting 的赋值丢失了,不过 lpthw.web 还是会给你一个挺好的错误页面,让你能找到出错的具体位置。 试试在这个错误页面上做以下操作:

  1. 检查每一段 Local vars 输出(用鼠标点击它们),追踪里边提到的变量名称,以 及它们是在哪些代码文件中用到的。
    网页错误提示:
 | self |  <app.index object at 0x103446750>
<bound method index.GET of <app.index object at 0x103446750>>

终端错误提示:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/lpthw.web-1.1-py2.7.egg/web/application.py", line 236, in process
    return self.handle()
  File "/usr/local/lib/python2.7/site-packages/lpthw.web-1.1-py2.7.egg/web/application.py", line 227, in handle
    return self._delegate(fn, self.fvars, args)
  File "/usr/local/lib/python2.7/site-packages/lpthw.web-1.1-py2.7.egg/web/application.py", line 409, in _delegate
    return handle_class(cls)
  File "/usr/local/lib/python2.7/site-packages/lpthw.web-1.1-py2.7.egg/web/application.py", line 384, in handle_class
    return tocall(*args)
  File "/Users/douyueyue/study/python_practise/projects/gothonweb/bin/app.py", line 11, in GET
    return greeting
NameError: global name 'greeting' is not defined
  1. 阅读 Request Information 一节,看看里边哪些知识是你已经熟悉了的。 Request 是浏览器发给你的gothonweb应用程序的信息。这些知识对于日常网页 浏览没有什么用处,但现在你要学会这些东西,以便写出 web 应用程序来。


    image.png

    image.png
  2. 试着把这个小程序的别的位置改错,探索一下会发生什么事情。lpthw.web 的会 把一些错误信息和堆栈跟踪(stack trace)信息显示在命令行终端,所以别忘了检查命 令行终端的信息输出。

创建基本的模板文件

这是一个 web 应用,所以需要一个合适的 HTML 响应页面才对。为了达到这个目的,下一步你要做的是将“Hello World” 以较大的绿色字体显示出来。
第一步是创建一个templates/index.html文件,内容如下:

$def with (greeting)
<!DOCTYPE html>
<html>
<head>
    <title>Gothons Of Planet Percal #25</title>
</head>
<body>
$if greeting:
    I just wanted to say <em style="color: green; font-size: 2em;">$greeting</em>.
$else:
    <em>Hello</em>, world!
</body>
</html>>

这里的HTML文件其实是个“模板(template)”,如果你向模板提供一个参数,lpthw.web就会在模板中找到对应的位置,将参数的内容填充到模板中去。例如index.html中每一个出现$greeting的位置,$greeting的内容都会被替换成对应这个变量名的参数。
为了让你的bin/app.py处理模板,你需要写一写代码,告诉lpthw.web到哪里去找到模板进行加载,以及如何渲染(render)这个模板,按照下面的方式修改你的app.py:

import web

urls = (
    '/', 'index'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class index(object):
    def GET(self):
        greeting = "Hello World"
        return render.index(greeting = greeting)
if __name__ == "__main__":
    app.run()

特别注意一下render这个新的变量名,我修改了index.GET的最后一行,让它返回了render.index(),并且将greeting变量作为参数传递给了这个函数。
改好上面的代码后,刷新网页,输出如下:


image.png

可以在浏览器中通过“查看源文件(view Source)”看到模板被渲染成了标准有效的HTML源代码:

<!DOCTYPE html>
<html>
<head>
        <title>Gothons Of Planet Percal #25</title>
</head>
<body>
    I just wanted to say <em style="color: green; font-size: 2em;">Hello World</em>.
</body>
</html>>
模板的工作原理
  1. 在bin/app.py里面添加的一个叫做render的新变量,它本身是一个web.template.render对象。
  2. 你将templates/作为参数传递给了这个对象,这样就让render知道了从哪里去加载模板文件。
  3. 在你后面的代码中,当浏览器一如既往的触发了index.GET以后,它没有再返回简单的greeting字符串,取而代之的是你调用了render.index,而且将问候语句作为一个变量传递给它。
  4. 这个render_template函数可以说是一个“魔法函数”,它看到了你需要的是index.html,于是跑到templates/目录下,找到名字为index.html的文件,然后就把它渲染(render)一遍。
  5. 在templates/index.html文件中,你可以看到初始定义一行中说这个文件需要使用一个叫做greeting的参数,这和函数定义中的格式差不多。另外和Python语法一样,模板文件是缩紧敏感的。
  6. 最后,你让templates/index.html去检查greeting这个变量,如果这个变量存在的话,就打印出变量的内容,如果不存在的话,就会打印出一个默认的问候信息。
加分题
  1. http://webpy.org/阅读里边的文档,它其实和lpthw.web是同一个项目。
  2. 实验一下你在上述网站看到的所有的东西,包括里边的代码示例。
  3. 阅读以下 HTML5 和 CSS3 相关的东西,自己练习着写几个 .html 和 .css 文件
  4. 如果你有一个懂 Django 朋友可以帮你的话,你可以试着使用 Django 完成一下习题 50、51、52,看看结果会是什么样子的。
首先安装Django:

Python环境与Django版本对应表:

image.png

参考:https://www.jianshu.com/p/9af73e184569
这里下载:DJango-1.x.y.tar.gz,在页面右侧列表下载:
下载后进入下载目录,双击解压
进入解压后的目录:

$ cd Django-1.x.y
$ sudo python setup.py install

成功后提示:

Processing dependencies for Django==1.x.y
Finished processing dependencies for Django==1.x.y

进入我们的项目目录,创建 Django 项目:

$ django-admin.py startproject testdj

启动服务:

cd testdj # 切换到我们创建的项目
$ python manage.py runserver
……
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

以上信息说明,项目已启动,访问地址为http://127.0.0.1:8000/。
可以来看下django-admin 的命令介绍:

$ django-admin

Type 'django-admin help <subcommand>' for help on a specific subcommand.

Available subcommands:

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    runserver
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver
Note that only Django core commands are listed as settings are not properly configured (error: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.).
使用 django-admin 来创建 HelloWorld 项目:
django-admin startproject HelloWorld

创建完成后我们可以查看下项目的目录结构:

image.png

目录说明:
HelloWorld: 项目的容器。
manage.py: 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。
HelloWorld/init.py: 一个空文件,告诉 Python 该目录是一个 Python 包。
HelloWorld/settings.py: 该 Django 项目的设置/配置。
HelloWorld/urls.py: 该 Django 项目的 URL 声明; 一份由 Django 驱动的网站"目录"。
HelloWorld/wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目。

在 HelloWorld 目录底下创建 templates 目录并建立 hello.html文件,整个目录结构如下:


image.png

hello.html 文件代码如下

<h1>I want to say:{{ hello }}</h1>

从模板中我们知道变量使用了双括号。

接下来我们需要向Django说明模板文件的路径,修改HelloWorld/settings.py,修改 TEMPLATES 中的 DIRS 为 [BASE_DIR+"/templates",],如下所示:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR+"/templates",],    # 修改位置
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

修改 view.py,增加一个新的对象,用于向模板提交数据:

from django.shortcuts import render

def hello(request):
    context = {}
    context['hello'] = 'Hello World! yeah~'
    return render(request, 'hello.html', context)

可以看到,我们这里使用 render 。render 还使用了一个字典 context 作为参数。context 字典中元素的键值 "hello" 对应了模板中的变量 "{{ hello }}"。
再访问访问 http://127.0.0.1:8000/hello,可以看到页面

image.png

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,096评论 0 3
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,424评论 1 45
  • Beetl2.7.16中文文档 Beetl作者:李家智 <xiandafu@126.com> 1. 什么是Beet...
    西漠阅读 2,650评论 0 0
  • 前言 开局一张图,姿势全靠yy 模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这大大提升...
    帅猪佩奇阅读 12,356评论 0 5
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,728评论 1 92