资讯专栏INFORMATION COLUMN

初识Bottle(二)

stormjun / 2990人阅读

摘要:而其他的引擎,例如能够帮我们进行验证登录自此,官网的我们已经大致有了了解后续我们可以选择运用该框架实现一些简单的应用,或者可以深入研究其源码,提升自身的编程水平

在初识Bottle(一)中,我们了解了Bottle的基本用法
在Bottle源码阅读(一)和Bottle源码阅读(二)可以查看个人对bottle源码的相关阅读笔记

下面继续阅读Bottle的官方文档https://bottlepy.org/docs/dev...

1.路由静态文件

在bottle中例如css等的文件是不会被自动加载的,因此需要自己定义callback函数,通过调用使用

from bottle import static_file
@route("/static/")
def server_static(filename):
    return static_file(filename, root="/path/to/your/static/files")
2.错误页

通过error装饰器可以对相应的错误码自定义对应的应用函数

from bottle import error
@error(404)
def error404(error):
    return "Nothing here, sorry"
3.内容返回

Bottl框架允许应用函数返回如下类型的结果

Dictionaries字典:
python的字典通过框架被转换为json字符串,而header中的Content-Type则会被设置为application/json

Empty Strings, False, None or other non-true values:
header中的Content-Length被设置为0

Unicode strings
Byte strings
Instances of HTTPError or HTTPResponse
File objects
Iterables and generators

4.改变默认编码

通过在应用函数中改变response的属性可以自定义

from bottle import response
@route("/iso")
def get_iso():
    response.charset = "ISO-8859-15"
    return u"This will be sent with ISO-8859-15 encoding."

@route("/latin9")
def get_latin():
    response.content_type = "text/html; charset=latin9"
    return u"ISO-8859-15 is also known as latin9."
5.静态文件的使用

通过static_file接口,我们可以实现调用和下载

from bottle import static_file
@route("/images/")
def send_image(filename):
    return static_file(filename, root="/path/to/image/files", mimetype="image/png")

@route("/static/")
def send_static(filename):
    return static_file(filename, root="/path/to/static/files")
    
@route("/download/")
def download(filename):
    return static_file(filename, root="/path/to/static/files", download=filename)
6.HTTP ERRORS AND REDIRECTS

通过abort可以快速定义错误码相应的错误页内容
redirect实现重定向

from bottle import route, abort
@route("/restricted")
def restricted():
    abort(401, "Sorry, access denied.")
    
from bottle import redirect
@route("/wrong/url")
def wrong():
    redirect("/right/url")
7.RESPONSE

response对象包括了响应的metadata例如状态码,headers,cookie等

response的状态码控制浏览器的行为,默认200ok
response的header可以通过set_header()来设置,对同一个header项,还可以通过add_header添加额外内容
cookie是保留在用户浏览器的一些数据,可以通过get_cookie和set_cookie来操作

@route("/hello")
def hello_again():
    if request.get_cookie("visited"):
        return "Welcome back! Nice to see you again"
    else:
        response.set_cookie("visited", "yes")
        return "Hello there! Nice to meet you"

cookie是容易被伪造的,所以Bottle框架提供了cookie的签名机制,只需要提供一个secret的参数作为密钥
Bottle会自动持久化和去持久化保存在cookie中的数据,cookie不超过4k。
此时cookie仍然能从浏览器中查看到,而且是可以被复制的,所以最好不要将密钥的信息放在用户客户端

@route("/login")
def do_login():
    username = request.forms.get("username")
    password = request.forms.get("password")
    if check_login(username, password):
        response.set_cookie("account", username, secret="some-secret-key")
        return template("

Welcome {{name}}! You are now logged in.

", name=username) else: return "

Login failed.

" @route("/restricted") def restricted_area(): username = request.get_cookie("account", secret="some-secret-key") if username: return template("Hello {{name}}. Welcome back.", name=username) else: return "You are not logged in. Access denied."
8.REQUEST

request 对象包括了Cookies, HTTP header, HTML

等一系列可以操作的对象

from bottle import request, route, template

@route("/hello")
def hello():
    name = request.cookies.username or "Guest"
    return template("Hello {{name}}", name=name)

Bottle使用FormsDict存储表单数据和cookie数据,而FormsDict的特定就是既具备了普通字典的操作方法,又能将key作为对象的属性,具体如下name既是字典的key又是cookies的属性

name = request.cookies.name

# is a shortcut for:

name = request.cookies.getunicode("name") # encoding="utf-8" (default)

# which basically does this:

try:
    name = request.cookies.get("name", "").decode("utf-8")
except UnicodeError:
    name = u""

同时,FormsDict还能对单个key存储多个值

for choice in request.forms.getall("multiple_choice"):
    do_something(choice)

request的query string会被分解为多个键值对,而通过request.query可以直接获得查询字符串对应键的值

from bottle import route, request, response, template
@route("/forum")
def display_forum():
    forum_id = request.query.id
    page = request.query.page or "1"
    return template("Forum ID: {{id}} (page {{page}})", id=forum_id, page=page)

上传文件时,我们需要在表单添加enctype="multipart/form-data", 同时将type设置为file


  Category:      
  Select a file: 
  

文件上传到服务端后

@route("/upload", method="POST")
def do_upload():
    category   = request.forms.get("category")
    upload     = request.files.get("upload")
    name, ext = os.path.splitext(upload.filename)
    if ext not in (".png",".jpg",".jpeg"):
        return "File extension not allowed."

    save_path = get_save_path_for_category(category)
    upload.save(save_path) # appends upload.filename automatically
    return "OK"

通过BaseRequest.body我们可以直接获取原始的请求体,也可以获取environ

@route("/my_ip")
def show_ip():
    ip = request.environ.get("REMOTE_ADDR")
    # or ip = request.get("REMOTE_ADDR")
    # or ip = request["REMOTE_ADDR"]
    return template("Your IP is: {{ip}}", ip=ip)
9.模板

Bottle内建了前端模板引擎,在官网给出的这个例子中,会加载./views/中的hello_template.tpl

@route("/hello")
@route("/hello/")
def hello(name="World"):
    return template("hello_template", name=name)
或者
@route("/hello")
@route("/hello/")
@view("hello_template")
def hello(name="World"):
    return dict(name=name)
%if name == "World":
    

Hello {{name}}!

This is a test.

%else:

Hello {{name.title()}}!

How are you?

%end

模板在编译后会被缓存到内存中,修改后需要执行bottle.TEMPLATES.clear()清除缓存模板

10.PLUGINS

Bottle提供了一系列的第三方引擎,这些能够有效地减少重复性工作
官网使用SQLitePlugin作为例子,在每一次调用需要与数据库进行交互的callback函数时,该引擎会自动创建连接和关闭连接。而其他的引擎,例如’auth‘能够帮我们进行验证登录

from bottle import route, install, template
from bottle_sqlite import SQLitePlugin

install(SQLitePlugin(dbfile="/tmp/test.db"))

@route("/show/")
def show(db, post_id):
    c = db.execute("SELECT title, content FROM posts WHERE id = ?", (post_id,))
    row = c.fetchone()
    return template("show_post", title=row["title"], text=row["content"])

@route("/contact")
def contact_page():
    """ This callback does not need a db connection. Because the "db"
        keyword argument is missing, the sqlite plugin ignores this callback
        completely. """
    return template("contact")
sqlite_plugin = SQLitePlugin(dbfile="/tmp/test.db")
install(sqlite_plugin)

uninstall(sqlite_plugin) # uninstall a specific plugin
uninstall(SQLitePlugin)  # uninstall all plugins of that type
uninstall("sqlite")      # uninstall all plugins with that name
uninstall(True)          # uninstall all plugins at once

自此,Bottle官网的tutorial我们已经大致有了了解
后续我们可以选择运用该框架实现一些简单的应用,或者可以深入研究其源码,提升自身的编程水平

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38445.html

相关文章

  • 初识 Bottle (一)

    摘要:安装是一个轻量型的不依赖于任何第三方库的框架,整个框架只有一个文件。向打声招呼吧新建一个文件在浏览器或者,,得到结果当使用装饰器绑定路由时,实际是使用了的默认应用,即是的一个实例。 1. 安装 bottle是一个轻量型的不依赖于任何第三方库的web框架,整个框架只有bottle.py一个文件。 wget http://bottlepy.org/bottle.py 2. 向bottl...

    mengbo 评论0 收藏0
  • Bottle源码阅读(一)

    摘要:在初识一中,我们了解了框架的基本用法。在本篇文章中,我们通过源码来探究一些基本原理。因此下一步就是研究我们写的应用函数是如何被封装成适配的 在初识bottle(一)中,我们了解了bottle框架的基本用法。在本篇文章中,我们通过源码来探究一些基本原理。 1. run的实现 所有的框架请求响应都基于一个原理http请求 --> wsgi服务器 --> wsgi接口(实际就是框架中自定义...

    whidy 评论0 收藏0
  • Bottle源码阅读(

    摘要:在源码阅读一中,我们了解了如何接收请求,处理请求以及如何检测模块变化重启。接下来我们看一下源码是怎么实现的经过封装后,最终获得的是具备有一些属性的装饰器当为时,将的属性传递给,使其具备相同的属性。 在《Bottle源码阅读(一)》中,我们了解了bottle如何接收请求,处理请求以及如何检测模块变化重启server。在ServerHandler类中的run函数中,application接...

    zzbo 评论0 收藏0
  • Bottle框架中的装饰器类和描述符应用

    摘要:最近在阅读微型框架的源码,发现了中有一个既是装饰器类又是描述符的有趣实现。所以第三版的代码可以这样写第三版的代码没有使用装饰器,而是使用了描述符这个技巧。更大的问题来自如何将描述符与装饰器结合起来,因为是一个类而不是方法。 最近在阅读Python微型Web框架Bottle的源码,发现了Bottle中有一个既是装饰器类又是描述符的有趣实现。刚好这两个点是Python比较的难理解,又混合在...

    Panda 评论0 收藏0
  • 使用python抓取百度漂流瓶妹纸照片

    摘要:无意中发现贴吧也出了个漂流瓶的东西,随手翻了翻发现居然有好多妹子图,闲来无事于是就想写个爬虫程序把图片全部抓取下来。具体获取一页内容的如下看参数很容易明白,就是当前页码,就是当前页中包含的漂流瓶数量。 showImg(https://segmentfault.com/img/bVLUTV?w=638&h=808); 无意中发现贴吧也出了个漂流瓶的东西,随手翻了翻发现居然有好多妹子图,闲...

    bang590 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<