码迷,mamicode.com
首页 > 其他好文 > 详细

How to build a blog 02:Suck World

时间:2014-08-26 11:28:45      阅读:363      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   使用   io   文件   for   

一、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定义了该空间类型是提交按钮,点击该按钮相当于按回车键

bubuko.com,布布扣

 

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

bubuko.com,布布扣

掌握了这些基本知识,就能够做一个简单的搜索框,让结果指向百度或者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方法

bubuko.com,布布扣

Get vs Post

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

三、认识更多的Form属性

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

bubuko.com,布布扣
<form>
    <input type="password" name="wd">
    <input type="submit">
</form>
View Code

 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>

bubuko.com,布布扣bubuko.com,布布扣

但是,单单使用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上显示相关信息

bubuko.com,布布扣

 

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)

运行效果如下:

bubuko.com,布布扣bubuko.com,布布扣

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

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

先编写对月份的验证

# 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!,结果显示如下

bubuko.com,布布扣

因为用户输入的">被当做特殊字符处理,所以才导致出错。我们需要用到转移字符。例如,要在浏览器打印<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)})

五、重定向

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

 

 bubuko.com,布布扣

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

  • 做一个“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)

 

How to build a blog 02:Suck World

标签:style   blog   http   color   os   使用   io   文件   for   

原文地址:http://www.cnblogs.com/ihuangmx/p/3930149.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!