How to build a blog 02:Suck World

一、Form标签简介

首先要学习的是表格标签<form>

<form action ="/foo">
    <input type = "text"  name = "test">
    <input type ="submit" value ="ClickOnMe">
</form>
  • <form> 表格标签
  • <form action ="url"> 表格所要提交的目的(where a form submit to)
  • <input type ="text"> input为输入控件,text定义了该控件类型是文本框
  • <input type ="submit"> intput为输入控件,submit定义了该空间类型是提交按钮,点击该按钮相当于按回车键

当输入123,然后点击ClickOnMe后,显示如下结果。

掌握了这些基本知识,就能够做一个简单的搜索框,让结果指向百度或者Google

<form action="http://www.baidu.com/s">
    <input name="wd">
    <input type="submit">
</form>

二、第一个应用程序:Suck World

先下载并安装GoogleAppEngine(自行百度),新建一个新的应用

import webapp2

class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write(‘Suck world!‘)

app = webapp2.WSGIApplication([
    (‘/‘, MainHandler)
], debug=True)
  • 当webapp2接受到一个对‘/‘(根路径)的请求时,会实例化MainHandler类,并调用get方法
  • 关于请求的信息,包含在self.request中
  • 如果遇到异常,debug=ture 会通知打印栈跟踪

接下来对程序进行修改,让它和知识点一最后给出的例子一样

import webapp2

# new string object from
form="""
<form action="http://www.baidu.com/s">
    <input name="wd">
    <input type="submit">
</form>
"""

#print form
class MainHandler(webapp2.RequestHandler):
    def get(self):
        #slef.resopne.headers[‘Content-Type‘] = ‘text/plain‘
        self.response.write(form)

app = webapp2.WSGIApplication([
    (‘/‘, MainHandler)
], debug=True)

GoogleApp自动将打印的信息当成html处理,如果你想打印纯文本,需要多添加一条:slef.resopne.headers[‘Content-Type‘] = ‘text/plain‘

接下来,我们让form的信息提交到自己创建的路径中,而不是提交到百度中

import webapp2

# new string object from
form="""
<form action="/testform">
    <input name="wd">
    <input type="submit">
</form>
"""

#print form
class MainHandler(webapp2.RequestHandler):
    def get(self):
        #slef.resopne.headers[‘Content-Type‘] = ""
        self.response.write(form)

class TestHandler(webapp2.RequestHandler):
    def get(self):
        wd = self.request.get("wd")
        self.response.write(wd)

app = webapp2.WSGIApplication([
    (‘/‘, MainHandler),
    (‘/testform‘,TestHandler)
], debug=True)
  • form的信息提交给了“/formtest",由于app只识别‘/‘,所以新建了一个(‘/testform‘,TestHandler)
  • TestHandler类中包含了以下信息:新建一个wd对象,用于储存请求信息中wd变量的信息,然后做出回应,打印wd变量

也可以让浏览器打印所有请求信息

#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import webapp2

# new string object from
form="""
<form action="/testform">
    <input name="wd">
    <input type="submit">
</form>
"""

#print form
class MainHandler(webapp2.RequestHandler):
    def get(self):
        #self.response.headers[‘Content-Type‘] = ‘text/plain‘
        self.response.write(form)

class TestHandler(webapp2.RequestHandler):
    def get(self):
        #wd = self.request.get("wd")
        #self.response.write(wd)
        self.response.headers[‘Content-Type‘] = ‘text/plain‘
        self.response.write(self.request)

app = webapp2.WSGIApplication([
    (‘/‘, MainHandler),
    (‘/testform‘,TestHandler)
], debug=True)

接下来介绍form标签的post属性,也就是post方法

POST:向指定的资源提交要被处理的数据

# new string object from
form="""
<form method="post"  action="/testform">
    <input name="wd">
    <input type="submit">
</form>
"""

#print form
class MainHandler(webapp2.RequestHandler):
    def get(self):
        #self.response.headers[‘Content-Type‘] = ‘text/plain‘
        self.response.write(form)

class TestHandler(webapp2.RequestHandler):
    def post(self):
        wd = self.request.get("wd")
        self.response.write(wd)
        #self.response.headers[‘Content-Type‘] = ‘text/plain‘
        #self.response.write(self.request)

app = webapp2.WSGIApplication([
    (‘/‘, MainHandler),
    (‘/testform‘,TestHandler)
], debug=True)

注意代码的两处改动,一个是在<form>标签中声明 method = post,也就是说,如果不声明,那么默认为get方法。另一处改动是TestHandler类的get方法要改名为post方法

Get vs Post

  • get方法常用于获取某个文件;post方法用于更新数据
  • get方法的参数保存在url中;post方法的参数保存在主体中
  • get方法的参数有长度限制;post方法的参数没有长度限制
  • get方法支持缓存,不必每次都请求;post方法不支持缓存
  • get方法无法改变服务端;post方法可以改变服务端

三、认识更多的Form属性

password属性:能让输入的文本以星号显示,但是结果能会在url中显示

<form>
    <input type="password" name="wd">
    <input type="submit">
</form>

checkbox属性:多选按钮,如果点击按钮,参数会以name=on的形式显示在浏览器中,否则则不会显示参数

<form>
    <input type="checkbox" name="wd">
    <input type="checkbox" name="r">
    <input type="checkbox" name="s">
    <br>
    <input type="submit">
</form>

radio属性:单选按钮控件,只需要为不同按钮赋予相同名字即可

<form>
    <input type="radio" name="wd">
    <input type="radio" name="wd">
    <input type="ra" name="wd">
    <br>
    <input type="submit">
</form>

但是,单单使用radio属性的话,不管点击哪一个,结果的url中都不会有提示点击哪一个的信息,只会显示wd=on。这时候,就需要借助value属性

<form>
    <input type="radio" name="wd" value="one">
    <input type="radio" name="wd" value="two">
    <input type="radio" name="wd" value="three">
    <br>
    <input type="submit">
</form>

选择第三个按钮,最终会在url上显示相关信息

label标签: input 元素定义标注(标记)

为上述按钮添加文本标注

<form>
    <label>
        One
        <input type="radio" name="wd" value="one">
    </label>

    <label>
        Two
        <input type="radio" name="wd" value="two">
    </label>

    <label>
        Three
          <input type="radio" name="wd" value="three">
    </label>
    <br>
    <input type="submit">
</form>

selcet:创建单选或者多选元素

<form>
    <select name="q">
        <option>one</option>
        <option>two</option>
        <option>three</option>
    </select>

    <br>
    <input type="submit">
</form>

url的信息会以q=one(two或者three)的形式来显示

如果要改变url显示的信息,可以借助value

<form>
    <select name="q">
        <option value="1">one</option>
        <option value="2">two</option>
        <option value="3">three</option>
    </select>

    <br>
    <input type="submit">
</form>

结果会以q=1(2或者3)的形式显示在url中

四、验证

验证服务端接受的内容是否是什么所期待的(what we receive is what we expect)

新建一个应用,让用户输入年/月/日

form="""
<form method="post">
    what is your birthday?
    <br>

    <label> Month
        <input type="text" name="month">
    </label>

    <label> Day
        <input type="text" name="day">
    </label>

    <label> Year
        <input type="text" name="year">
    </label>

    <br>
    <input type="submit">
</form>
"""
class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write(form)

    def post(self):
        self.response.write("Thanks!")

app = webapp2.WSGIApplication([
    (‘/‘, MainHandler)
], debug=True)

运行效果如下:

我们知道,年月日的输入是有限定的,可以采取两种方式对用户输入的数字进行限定:

  • 用下拉列表的方式呈现所有合法的选项,供用户选择
  • 对用户输入的信息进行验证

先编写对月份的验证

# judge the input of month is what we expect
#新建一个字典,来保存12个月的信息
months = [‘janurary‘,
         ‘February‘,
         ‘March‘,
         ‘April‘,
         ‘May‘,
         ‘june‘,
         ‘july‘,
         ‘August‘,
         ‘September‘,
         ‘October‘,
         ‘November‘,
         ‘December‘

]

def valid_month(month):
    if month:
                #将用户输入的月份的首字母大写化
        cap_month = month.capitalize()
               #遍历字典,看首字母大写化之后的月份是否在里面
    if cap_month in months:
        return cap_month
    else:
        print("not legal")
        return None

可以稍微修改,只校验前三个字母即可

# judge the input of month is what we expect
months = [‘janurary‘,
         ‘February‘,
         ‘March‘,
         ‘April‘,
         ‘May‘,
         ‘june‘,
         ‘july‘,
         ‘August‘,
         ‘September‘,
         ‘October‘,
         ‘November‘,
         ‘December‘

]

month_abbvs = dict((m[:3].lower(), m) for m in months)

def valid_month(month):
    if month:
        short_month = month[:3].lower()
        return month_abbvs.get(short_month)
               

对日期的验证较为简单,现在只是简单的验证,没有具体到某个月最大天数

def valid_day(day):
    if day and day.isdigit():
        day = int(day)
        if day > 0 and day <= 31:
            return day

对年份的验证和日期验证类似

def valid_year(year):
    if year and year.isdigit():
        year1 = int(year)
        if year > 1900 and year <2020:
            return year

接下来就可以将其整合到应用中了,先了解下整个验证的过程

  1. =》用户获取表格信息(get form)
  2. 《= 服务器返回表格页面(form date)
  3. =》用户提交表格信息(post date)
  4. 服务端对其进行验证:验证成功,返回感谢页面;验证失败,返回表格页面

也就是说,我们的验证机制应该包括三个方面的内容:

  • 验证用户的输入是否合法
  • 如果不合法的话,再次返回表格输入页面
  • 提示错误信息
import webapp2

def valid_day(day):
    if day and day.isdigit():
        day = int(day)
        if day > 0 and day <= 31:
            return day

def valid_year(year):
    if year and year.isdigit():
        year = int(year)
        if year > 1900 and year <2020:
            return year

# judge the input of month is what we expect
months = [‘janurary‘,
         ‘February‘,
         ‘March‘,
         ‘April‘,
         ‘May‘,
         ‘june‘,
         ‘july‘,
         ‘August‘,
         ‘September‘,
         ‘October‘,
         ‘November‘,
         ‘December‘

]

month_abbvs = dict((m[:3].lower(), m) for m in months)

def valid_month(month):
    if month:
        short_month = month[:3].lower()
        return month_abbvs.get(short_month)

form="""
<form method="post">
    what is your birthday?
    <br>

    <label> Month
        <input type="text" name="month">
    </label>

    <label> Day
        <input type="text" name="day">
    </label>

    <label> Year
        <input type="text" name="year">
    </label>

    <br>
    <input type="submit">
</form>
"""

class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write(form)

    def post(self):
        user_month = valid_month(self.request.get(‘month‘))
        user_day = valid_day(self.request.get(‘day‘))
        user_year = valid_year(self.request.get(‘year‘))

        # not x means if x is any kind of zero or empty container, or False...
        if not (user_month and user_day and user_year):
            self.response.write(form)
        else:
            self.response.write("Thanks! That‘s a totally valid date !")

app = webapp2.WSGIApplication([
    (‘/‘, MainHandler)
], debug=True)

程序不过是按照刚才的分析来做,在post方法下添加了对用户数据输入的验证,然后判断是否合法,并根据不同判断返回不同信息。不过该程序还差一样提示错误信息。

先补充一个字符串替代的知识,共有三种方式可以在字符串中嵌入变量:

t1 = "I think %s is perfectly normal things to do in public"
def sub1(s):
    return t1 %s

t2 = "I think %s and %s are perfectly normal things to do in public"
def sub2(s1,s2):
    return t2 %(s1,s2)

t3 = "I‘m %(nickname)s. My real name is %(name)s, but my friend all call me %(nickname)s"
def sub_3(name, nickname):
    return t3 %{‘name‘:name, ‘nickname‘:nickname}

除了提示错误信息之外,还增加了一个功能:当用户输入错误信息的时候,错误信息仍然显示在文本框里面,以避免用户需要全部重新输入一遍

import webapp2

def valid_day(day):
    if day and day.isdigit():
        day = int(day)
        if day > 0 and day <= 31:
            return day

def valid_year(year):
    if year and year.isdigit():
        year = int(year)
        if year > 1900 and year <2020:
            return year

# judge the input of month is what we expect
months = [‘janurary‘,
         ‘February‘,
         ‘March‘,
         ‘April‘,
         ‘May‘,
         ‘june‘,
         ‘july‘,
         ‘August‘,
         ‘September‘,
         ‘October‘,
         ‘November‘,
         ‘December‘

]

month_abbvs = dict((m[:3].lower(), m) for m in months)

def valid_month(month):
    if month:
        short_month = month[:3].lower()
        return month_abbvs.get(short_month)

#嵌入了四个变量 month,day,year,error
form="""
<form method="post">
    what is your birthday?
    <br>

    <label> Month
        <input type="text" name="month" value="%(month)s">
    </label>

    <label> Day
        <input type="text" name="day" value="%(day)s">
    </label>

    <label> Year
        <input type="text" name="year" value="%(year)s">
    </label>

    <div style="color:red">%(error)s</div>
    <br>
    <input type="submit">
</form>
"""

class MainHandler(webapp2.RequestHandler):
    #因为根据数据合法性所返回的结果是不同的,所以统一用一个函数编写
    def  write_form(self,error="",month="",day="",year=""):
        self.response.write(form %{"error": error,
                                   "month": month,
                                   "day": day,
                                   "year": year})

   #step1:获取表格信息,四个变量不需要任何参数
    def get(self):
        self.write_form()

    #setp2:用户提交表格信息
    def post(self):
        #获取用户输入信息
        user_month = self.request.get(‘month‘)
        user_day = self.request.get(‘day‘)
        user_year = self.request.get(‘year‘)

        #判断输入信息合法与否
        month = valid_month(user_month)
        day = valid_day(user_day)
        year = valid_year(user_year)

        # not x means if x is any kind of zero or empty container, or False...
        if not (month and day and year):
           #如果数据输入没有通过验证,除了返回错误信息外,还返回原来用户的输入信息
            self.write_form("That donesn‘t look valid to me ,friend.",
                             user_month, user_day, user_year)
        else:
            self.response.write("Thanks! That‘s a totally valid date !")

app = webapp2.WSGIApplication([
    (‘/‘, MainHandler)
], debug=True)

上述的程序仍然有bug,就是文本框无法对输入字符进行处理,例如,在月份那栏输入foo">drep!,结果显示如下

因为用户输入的">被当做特殊字符处理,所以才导致出错。我们需要用到转移字符。例如,要在浏览器打印<html>应该如何打印?正确方式是用 < 与 > 的转义字符来替代

What if i want to talk about <html> in html?
What if i want to talk about &lt;html&gt;in html?

&:&amp;

<: &lt;

>: &gt;

" : &quot;

那么,如何解决上述问题呢?

编写函数,用于将用户在文本框输入的内容转化成转义字符,python本身也有内置模块(cgi)直接支持

#import cgi
def escape_html(s):
    #return cgi.escape(s,quote = True)
    for(i,o) in (("&","&amp;"),
                 (">","&gt;"),
                 ("<","&lt;"),
                 (‘"‘,"&quot;")):
        s = s.replace(i,o)
    return s

然后重写write_form函数即可

 def  write_form(self,error="",month="",day="",year=""):
        self.response.write(form %{"error": error,
                                   "month": escape_html(month),
                                   "day": escape_html(day),
                                   "year": escape_html(year)})

五、重定向

当我们输入正确的日期时,会返回一个感谢界面

如果解决上述的两个问题?答案就是给对返回的页面进行重定向,包括以下三个步骤:

  • 做一个“thank"的hander
  • 添加 /thank的url
  • 进行定向
 # not x means if x is any kind of zero or empty container, or False...
        if not (month and day and year):
            self.write_form("That donesn‘t look valid to me ,friend.",
                             user_month, user_day, user_year)
        else:
           #进行定向
            self.redirect("/thanks")

#添加Thank的Handler
class ThanksHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write("Thanks! That‘s a totally valid date !")

#添加thank的url
app = webapp2.WSGIApplication([
    (‘/‘, MainHandler),(‘/thanks‘,ThanksHandler)
], debug=True)
时间: 2024-11-05 20:32:19

How to build a blog 02:Suck World的相关文章

How to build a blog 01:Web基础知识

一.Internet基础知识 1. Internet的出现后,我们可以从本地(客户端)访问世界各地(服务器)的各种资源,最基本的客户端就是Web浏览器. 2. HTTP协议,则定义了客户端与服务器应该如何通讯,比如规定传输的数据的格式,这样的话我们就不用去担心数据在传输过程中是否会损坏.所以,你可以发现网站的开头,大多数是HTTP开头的,代表了使用该协议进行通讯 3. 但是,服务器众多,比如单单视频网站就有youku.爱奇艺.乐视.搜狐TV等,为了识别不同的服务端,每台服务就有了自己的独特的名字

机器学习中的矩阵方法02:正交

机器学习中的矩阵方法02:正交 说明:Matrix Methods in Data Mining and Pattern Recognition 读书笔记 1. 正交的一些概念和性质 在前一章的最小二乘的问题中,我们知道不恰当的基向量会出现条件数过大,系统防干扰能力差的现象,这实际上和基向量的正交性有关. 两个向量的内积如果是零, 那么就说这两个向量是正交的,在三维空间中,正交的两个向量相互垂直.如果相互正交的向量长度均为 1, 那么他们又叫做标准正交基. 正交矩阵则是指列向量相互正交的方阵.标

Linux江湖02:打造属于自己的Vim

Linux系统中很多东西都是以脚本代码.配置文件的形式存在,使用Linux系统时,需经常对这些文件进行编辑.很显然,如果没有文本编辑器,江湖之路寸步难行. 我的选择是Vim.Vim是Linux系统上的最著名的文本/代码编辑器,也是早年的Vi编辑器的加强版,被誉为文本/代码编辑器之中最为优秀经典的上古神器. 它之所以会获得如此美誉,我想主要有以下原因:1.它古老而神秘,学习曲线陡峭,难以驾驭,但是一旦学会则受益匪浅.如今被看作是高手.Geek们专用的编辑器.所以尽管 Vim 已经是古董级的软件,但

【Ext.Net学习笔记】02:Ext.Net用法概览、Ext.Net MessageBus用法、Ext.Net布局

Ext.Net用法概览 Ext.Net还是很强大,如果运用熟练可以极大的提高编程效率.如果你也要学习Ext.Net,原文博主推荐书籍:<Ext.Net Web 应用程序开发教程>,是英文的,有基础的可以看下,可以百度到PDF文档的. Ext.Net与ExtJS代码比较 上一篇中我们创建了一个使用Ext.Net创建了一个window窗口,代码非常简单: <ext:Window runat="server" ID="win" Title="示

[转载]AngularJS入门教程02:AngularJS模板

是时候给这些网页来点动态特性了——用AngularJS!我们这里为后面要加入的控制器添加了一个测试. 一个应用的代码架构有很多种.对于AngularJS应用,我们鼓励使用模型-视图-控制器(MVC)模式解耦代码和分离关注点.考虑到这一点,我们用AngularJS来为我们的应用添加一些模型.视图和控制器. 请重置工作目录: git checkout -f step-2 我们的应用现在有了一个包含三部手机的列表. 步骤1和步骤2之间最重要的不同在下面列出.,你可以到GitHub去看完整的差别. 视图

Angular系列----AngularJS入门教程02:静态模板(转载)

为了说明angularJS如何增强了标准HTML,我们先将创建一个静态HTML页面模板,然后把这个静态HTML页面模板转换成能动态显示的AngularJS模板. 在本步骤中,我们往HTML页面中添加两个手机的基本信息,用以下命令将工作目录重置到步骤1. git checkout -f step-1 请编辑app/index.html文件,将下面的代码添加到index.html文件中,然后运行该应用查看效果. app/index.html <ul> <li> <span>

Java泛型解析(02):通配符限定

Java泛型解析(02):通配符限定 考虑一个这样的场景,计算数组中的最大元素. [code01] public class ArrayUtil { public static <T> T max(T[] array) { if (array == null || 0 == array.length) { return null ;} T max = array[0]; for (int i = 1; i < array.length; i++) { if (max.compareTo(

如何看透他人行为背后的本质 | 思维模型02:行为分析模型

阿牛(皱眉):辣鸡啊,你们团队新来的那个小白,业绩不怎么样啊,怎么回事儿? 辣鸡(一激灵):老板,小白的能力和态度都挺好的.可能是因为刚入职没多久,对自己的工作重点把握不好. 阿牛(更加不满):哦,那你作为他老板,怎么没好好引导一下? 辣鸡(指指手机):我也想啊老板,可实在太忙抽不出空.我连陪女朋友的时间都没了,她说我不在乎她,天天找我吵架,喏,你听. 阿牛(和颜悦色):最近的确辛苦你了,天天加班啊. 辣鸡(几近崩溃):可不,上周听你讲了"可得性偏差模型",我就毫无怨言地加班了. 阿牛

平时的笔记02:处理mp3

#! /usr/bin/env python # # mutagen aims to be an all purpose media tagging library # Copyright (C) 2005  Michael Urman # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Publi