数据与路由

作者: 网络编程  发布:2019-07-11

将视图函数拆分到单独的文书中

  1. 万一视图函数都写在主文件中,不方便人民群众体贴,而是应该把她们放入到二个文书中,每四个模块正是贰个试图,用的时候平昔引用,那样方便爱护
  2. 在根目录下树立二个app/web文件夹,在那几个文件夹下边创建叁个book.py文件,专门用来存放在book模块,然后在主文件中援引这些模块就足以了,book.py
# -*- coding: utf-8 -*-
from flask import jsonify
from helper import is_isbn_key
from ShanqiuBook import ShanqiuBook

# 为了让book.py模块可以使用app对象
from demo import app

@app.route('/book/search/<q>/<page>')
def hello(q,page):

    # 调用方法判断用户是根据什么查的
    is_or_key = is_isbn_key(q)
    if is_or_key == 'isbn':
        result = ShanqiuBook.search_by_isbn(q)
    else:
        result = ShanqiuBook.search_by_keyword(q)

    return jsonify(result)
  1. 那时候的主文件中
# -*- coding: utf-8 -*-
from flask import Flask
# 为了可以注册book.py中的路由
from app.web import book

app = Flask(__name__)
app.config.from_object('config')

if __name__ == '__main__':
    app.run(debug=app.config['DEBUG'])
  1. 不过这么写的话,会产出404,因为出现了巡回引用

五、WTForms参数验证

  1. 上面大家把url改了,可是要是用户输入了有些特有的符号该怎么做?那年就要采纳到参数验证,而WTForms框架就是多个一石两鸟的参数验证框架,首先在相应的条件中进行设置(flask--yQglGu4) E:pyqiyueflask>pipenv install wtforms
  2. 其一参数验证写在哪里好吧,直接写在book.py中,这样是最不妥的,为了有助于调用,应该写成一个类,所以写在app/forms/book.py文件中
# -*- coding: utf-8 -*-

# 导入需要使用的模块
from wtforms import Form,StringField,IntegerField
from wtforms.validators import Length,NumberRange

class SearchForm(Form):
    # 直接调用内置对象
    # 参数校验规则:
    # 1.定义的属性名q,page要与要校验的参数同名
    # 2.根据要传入的参数类型选择不同的Field类进行实例化
    # 3.传入一个数组,作为校验规则validators
    # 4.可以设置默认值
    q = StringField(validators=[DataRequired(),Length(min=1,max=30)])

    page = IntegerField(validators=[NumberRange(min=1,max=10)],default=1)
  1. 那时在app/web/book.py文件中就足以一向调用就行了
# -*- coding: utf-8 -*-
from flask import jsonify, Blueprint,request
from helper import is_isbn_key
from ShanqiuBook import ShanqiuBook
from . import web
# 导入参数校验
from app.forms.book import SearchForm

# http://127.0.0.1:5000/book/search/?q=金庸&page=1
@web.route('/book/search/')
def hello():

    # 验证层
    # 实例化我们自定义的SearchForm,需要传入一个字典作为要校验的参数
    form  = SearchForm(request.args)
    # validate()方法返回True/False来标示是否校验通过
    if form.validate():

        # 从form中取出校验后的q与page,并且清除空格
        q = form.q.data.strip()
        page = form.page.data

        is_or_key = is_isbn_key(q)
        if is_or_key == 'isbn':
            result = ShanqiuBook.search_by_isbn(q)
        else:
            result = ShanqiuBook.search_by_keyword(q)
        return jsonify(result)
    else:
        return jsonify({'msg':'参数校验失败'})

requests请求

  1. 因为那个类型要访问分歧的网站,所以在目录下新建三个http.py文本,特地用来提供访问网站
  2. 此间运用的requests,要先举行设置,注意:代码写的时候肯定要简明,相对不要选择python的最首要字,防止与Python的模块争执并促成此错误,把那个类名http改为其他名称
# -*- coding: utf-8 -*-

import requests
class aaa:

    # 传入url和是否返回的是json数据,这里是静态方法
    @staticmethod
    def get(url,return_json=True):
        # 发送get请求
        r = requests.get(url)
        # 因为有的url返回的json数据,但是有的并不是,所以加一个判断,不是的话返回文本
        # 还要判断状态码,200的话就是访问成功有数据
        if r.status_code != 200:
            return {} if return_json else ''
        return r.json() if return_json else r.text

        # 下面的写法太low
        # if r.status_code == 200:
        #     if return_json:
        #         return r.json()
        #     else:
        #         return r.text
        # else:
        #     if return_json:
        #         return {}
        #     else:
        #         return ''

一、应用、蓝图与视图函数

  1. 结构,如图:

    图片 1

  2. Flask最上层是app核心对象 ,在这么些宗旨目的上能够插入非常多蓝图,这一个蓝图是不可能独立存在的,必须将app作为插板插入app ,在每多少个蓝图上,能够登记成都百货上千静态文件,视图函数,模板 ,二个作业模块能够做为贰个蓝图,举个例子book,从前的book.py 放到了app/web/路径下,正是思虑到了蓝图,app属于是一切Flask应用层,web属于是蓝图

  3. 一对早先化操作应该归入到__init__文件中,比方Flask的着力应用app起头化对象,应该归入到在选取层级app包的 __init__.py 中 ,而蓝图的开头化应该纳入到蓝图层的web包__init__.py中,如图:

    图片 2

  4. Flask的中坚应用app初叶化对象文件app/__init__.py

# -*- coding: utf-8 -*-
from flask import Flask

def create_app():
    app = Flask(__name__)
    app.config.from_object('config')
    # 要返回回去
    return app
  1. 那时在主文件中
# -*- coding: utf-8 -*-
from app import create_app

app = create_app()

if __name__ == '__main__':
    app.run(debug=app.config['DEBUG'])

探索关键字

  1. 基于地点的地点能够理解搜索的时候有二种方法,而对于isbn寻觅,又分为二种isbn13 由13个0-9在数字组成,isbn10 由10表0-9表数字组组成,中间可能包含' - ' ,进而要分手来决断
  2. 在函数中要小心:isdigit()能够看清是不是为数字 ,replace()用来替换,
@app.route("/search/<q>/<page>")
def search(q,page):
    """
    搜索书籍路由
    :param q: 关键字 OR isbn
    :param page: 页码
    """
    isbn_or_key = 'key'
    # 1. 判断长度是否为13且是否为数字
    if len(q) == 13 and q.isdigit():
        isbn_or_key = 'isbn'
    # 2. 把-替换掉,判断是否为纯数字
    short_q = q.replace('-', '')
    if '-' in q and len(short_q) == 10 and short_q.isdigit():
        isbn_or_key = 'isbn'
    pass
  1. 多逻辑剖断的时候,应该把结果望着为假的嵌入后面,对数据库操作的放置后边,那样便于节约财富

六、拆分配置文件

  1. 事先访谈数据的时候,count和start都以写死的,未来来进展重构,在此之前的代码
   @classmethod
    def search_by_key(cls, q, count=15, start=0):
        # count:每页显示的数量
        # start:每页的第一条数据的下标
        url = cls.search_by_key_url.format(q, count, start)
        return HTTP.get(url)
  1. 与此相类似写非常的不妥

    • 在视图函数中收取到的参数是page,代码的封装性,我们相应把count和start的测算进度置于ShanqiuBook.py的 search_by_key方法中来写

    • count的值为了便于日后的保管,那一个相应放入到铺排文件中,此前的陈设文件是config.py,在根目录下,而那么些应该放入到app目录下,而有关部分比较隐衷的布署音信要妥当处理,所以在app目录下创立八个文件,secure.py用来贮存在私密的配备音信,setting.py用于贮存一些不主要的布置音信,如下

    • app/secure.py

      # -*- coding: utf-8 -*-
      
      # 存放比较机密的配置文件,在上传git的时候不应该上传此文件
      DEBUG = True
      
    • app/setting.py

      # -*- coding: utf-8 -*-
      
      # 生产环境和开发环境几乎一样的,不怎么机密的配置文件
      
      # 每页显示的数据量
      PER_PAGE = 15
      
    • start的乘除是叁个独立的逻辑,应该用封装成三个艺术,使用的时候一贯调用

      # 获取每一页的起始下标
          @staticmethod
          def calculate_start(page):
              # 获取配置信息中的每页显示的数量
              return (page -1 ) * current_app.config['PER_PAGE']
      
  2. 重构后的ShanqiuBook.py

   -*- coding: utf-8 -*-
   from httper import httper
# 通过这种方式来导入当前的app对象,方便调用配置而文件

   from flask import current_app

   class ShanqiuBook:

   isbn_url = 'http://t.yushu.im/v2/book/search/isbn/{}'
   keyword_url = 'http://t.yushu.im/v2/book/search?q={}&count={}&start={}'

   @classmethod
   def search_by_isbn(cls,isbn):
       url = cls.isbn_url.format(isbn)
       result = httper.get(url)
       return result

   @classmethod
   def search_by_keyword(cls,keyword,page=1):
       # 每页显示的数据(通过这种方式从配置文件中获取到),每一页的起始下标
       url = cls.keyword_url.format(keyword,current_app.config['PER_PAGE'],cls.calculate_start(page))
       result = httper.get(url)
       return result

# 获取每一页的起始下标
   @staticmethod
   def calculate_start(page):
       return (page -1 ) * current_app.config['PER_PAGE']​
  1. 以此时候在app/__init__.py文本中把陈设文件增添到app中
#-- coding: utf-8 --

from flask import Flask

def create_app():

    app = Flask(name)

    # app.config.from_object('config')

    # 把配置文件装载进来

    app.config.from_object('app.secure')

    app.config.from_object('app.setting')

    register_blueprint(app)

    return app

def register_blueprint(app):

    from app.web.book import web

    app.register_blueprint(web)

简轻易单的重构

  1. 地点的代码都写到视图中如此不妥,呈现不了封装性,看起来倒霉,应该把一个落到实处的成效封装起来,建设构造三个函数,方便日后的治本
  2. 在目录下建设构造一个helper.py文本,那些文件重大正是提供部分方法,把地点的剧情放到这里,只要求回到三个值就能够了
# -*- coding: utf-8 -*-

def is_isbn_or_key(word):
    isbn_or_key = 'key'
    if len(word) == 13 and word.isdigit():
        isbn_or_key = 'isbn'

    short_word = word.replace('-', '')
    if '-' in word and len(short_word) == 10 and short_word.isdigit():
        isbn_or_key = 'isbn'

    return isbn_or_key
  1. 在主文件中调用那一个格局就足以了,记得传值,和接收重回的值
# -*- coding: utf-8 -*-

from flask import Flask,make_response
# 1. 这里要导入
from helper import is_isbn_or_key

app = Flask(__name__)
app.config.from_object('config')

@app.route('/book/search/<q>/<page>')
def search(q,page):
    # 2. 调用方法即可
    is_or_key = is_isbn_or_key(q)
    pass

if __name__ == '__main__':
    app.rundebug=app.config['DEBUG'])

四、Request对象

  1. 在app/web/book.py文件中,定义的url请求是/book/search/<q>/<page>这种格式的,Flask会将<>里的值自动映射成视图函数方法的参数,不过这种格式用着不爽,要把用户输入的参数作为诉求参数字传送入,这一年将在选用这种格式了http://127.0.0.1:5000/book/search/?q=金庸&page=1
  2. 本条该怎么获取值呢,这年就用到Flask内置的Request了,通过request对象就足以获取HTTP乞请中隐含的详细消息了,具体的用法看下边包车型地铁代码
# -*- coding: utf-8 -*-

# 导入这个request模块,
from flask import jsonify, Blueprint,request
from helper import is_isbn_key
from ShanqiuBook import ShanqiuBook
from . import web

# http://127.0.0.1:5000/book/search/?q=金庸&page=1
@web.route('/book/search/')
def hello():
    # 通过Request对象拿到对应值的信息,但是这个并不是py中原始的字典,而是dict的子类immutableDict
    q = request.args['q']
    page = request.args['page']
    # ip = request.remote_addr

    # 通过这个方法把它转换为普通的dict
    # a = request.args.to_dict()
    # print(a)

    is_or_key = is_isbn_key(q)
    if is_or_key == 'isbn':
        result = ShanqiuBook.search_by_isbn(q)
    else:
        result = ShanqiuBook.search_by_keyword(q)

    return jsonify(result)
  1. Flask的request是依据代理格局实现的,想让request符合规律使用,必须确认保障是http乞请触发的函数或视图函数中运用

本文由金沙澳门官网发布于网络编程,转载请注明出处:数据与路由

关键词: 金沙澳门官网

上一篇:学习第一章,简介与入门
下一篇:没有了