文档章节

浅析tornado 中demo的 blog模块

沉淀岁月
 沉淀岁月
发布于 2016/09/06 22:32
字数 1052
阅读 41
收藏 0

​#!/usr/bin/env python

#

# Copyright 2009 Facebook

#

# 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 markdown

import os.path

import re

import torndb

import tornado.auth

import tornado.httpserver

import tornado.ioloop

import tornado.options

import tornado.web

import unicodedata

 

from tornado.options import define, options

#定义一些通用的配置信息,比如数据库的连接信息,端口信息

define("port", default=8888, help="run on the given port", type=int)

define("mysql_host", default="127.0.0.1:3306", help="blog database host")

define("mysql_database", default="blog", help="blog database name")

define("mysql_user", default="root", help="blog database user")

define("mysql_password", default="sa123", help="blog database password")

 

#定义Application信息,它是继承tornado.web.Application 的

class Application(tornado.web.Application):

   # __init__ 函数自动调用

    def __init__(self):

      #这里就是url对应的控制器,下面分别对应一个类,来处理里面的逻辑

        handlers = [

            (r"/", HomeHandler),

            (r"/archive", ArchiveHandler),

            (r"/feed", FeedHandler),

            (r"/entry/([^/]+)", EntryHandler),

            (r"/compose", ComposeHandler),

            (r"/auth/login", AuthLoginHandler),

            (r"/auth/logout", AuthLogoutHandler),

        ]

      #设置,如博客标题,模板目录,静态文件目录,xsrf,是否调试

        settings = dict(

            blog_title=u"Tornado Blog",

            template_path=os.path.join(os.path.dirname(__file__), "templates"),

            static_path=os.path.join(os.path.dirname(__file__), "static"),

            ui_modules={"Entry": EntryModule},

            xsrf_cookies=True,

            cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",

            login_url="/auth/login",

            debug=True,

        )

       #然后调用tornado.web.Application类的__init__函数加载进来

        tornado.web.Application.__init__(self, handlers, **settings)

 

        # Have one global connection to the blog DB across all handlers

       #数据库连接信息

        self.db = torndb.Connection(

            host=options.mysql_host, database=options.mysql_database,

            user=options.mysql_user, password=options.mysql_password)

 

#基类,继承自tornado.web.RequestHandler 的,后面的类都是继承这个类的

class BaseHandler(tornado.web.RequestHandler):

  #属性装饰器,使db函数变成一个属性,便于后面直接使用

    @property

    def db(self):

        return self.application.db

  #获得当前的用户

    def get_current_user(self):

        user_id = self.get_secure_cookie("blogdemo_user")

        if not user_id: return None

        return self.db.get("SELECT * FROM authors WHERE id = %s", int(user_id))

 

#首页

class HomeHandler(BaseHandler):

    def get(self):

     #query 查询很多列

        entries = self.db.query("SELECT * FROM entries ORDER BY published "

                                "DESC LIMIT 5")

        if not entries:

         #redirect 重定向到一个url

            self.redirect("/compose")

            return

     #render 渲染一个模板,后面是参数

        self.render("home.html", entries=entries)

 

 

class EntryHandler(BaseHandler):

    def get(self, slug):

    #get 得到一个值

        entry = self.db.get("SELECT * FROM entries WHERE slug = %s", slug)

    #raise 触发一个错误信息,后面必须接类型

        if not entry: raise tornado.web.HTTPError(404)

        self.render("entry.html", entry=entry)

 

 

class ArchiveHandler(BaseHandler):

    def get(self):

        entries = self.db.query("SELECT * FROM entries ORDER BY published "

                                "DESC")

        self.render("archive.html", entries=entries)

 

 

class FeedHandler(BaseHandler):

    def get(self):

        entries = self.db.query("SELECT * FROM entries ORDER BY published "

                                "DESC LIMIT 10")

        self.set_header("Content-Type", "application/atom+xml")

        self.render("feed.xml", entries=entries)

 

 

class ComposeHandler(BaseHandler):

    #装饰器

    @tornado.web.authenticated

    def get(self):

        id = self.get_argument("id", None)

        entry = None

        if id:

            entry = self.db.get("SELECT * FROM entries WHERE id = %s", int(id))

        self.render("compose.html", entry=entry)

 

    @tornado.web.authenticated

    def post(self):

        id = self.get_argument("id", None)

        title = self.get_argument("title")

        text = self.get_argument("markdown")

        html = markdown.markdown(text)

        if id:

            entry = self.db.get("SELECT * FROM entries WHERE id = %s", int(id))

            if not entry: raise tornado.web.HTTPError(404)

            slug = entry.slug

          #execute是执行的意思

            self.db.execute(

                "UPDATE entries SET title = %s, markdown = %s, html = %s "

                "WHERE id = %s", title, text, html, int(id))

        else:

            slug = unicodedata.normalize("NFKD", title).encode(

                "ascii", "ignore")

            slug = re.sub(r"[^\w]+", " ", slug)

            slug = "-".join(slug.lower().strip().split())

            if not slug: slug = "entry"

            while True:

                e = self.db.get("SELECT * FROM entries WHERE slug = %s", slug)

                if not e: break

                slug += "-2"

            self.db.execute(

                "INSERT INTO entries (author_id,title,slug,markdown,html,"

                "published) VALUES (%s,%s,%s,%s,%s,UTC_TIMESTAMP())",

                self.current_user.id, title, slug, text, html)

        self.redirect("/entry/" + slug)

 

 

class AuthLoginHandler(BaseHandler, tornado.auth.GoogleMixin):

    @tornado.web.asynchronous

    def get(self):

        if self.get_argument("openid.mode", None):

            self.get_authenticated_user(self.async_callback(self._on_auth))

            return

        self.authenticate_redirect()

  #这里定义一个函数,来供上面调用

    def _on_auth(self, user):

        if not user:

            raise tornado.web.HTTPError(500, "Google auth failed")

        author = self.db.get("SELECT * FROM authors WHERE email = %s",

                             user["email"])

        if not author:

            # Auto-create first author

            any_author = self.db.get("SELECT * FROM authors LIMIT 1")

            if not any_author:

                author_id = self.db.execute(

                    "INSERT INTO authors (email,name) VALUES (%s,%s)",

                    user["email"], user["name"])

            else:

                self.redirect("/")

                return

        else:

            author_id = author["id"]

        self.set_secure_cookie("blogdemo_user", str(author_id))

        self.redirect(self.get_argument("next", "/"))

 

 

class AuthLogoutHandler(BaseHandler):

    def get(self):

        self.clear_cookie("blogdemo_user")

      #get_argument为获得next参数的值,默认为"/"

        self.redirect(self.get_argument("next", "/"))

 

 

class EntryModule(tornado.web.UIModule):

    def render(self, entry):

        return self.render_string("modules/entry.html", entry=entry)

 

#入口函数

def main():

    tornado.options.parse_command_line()

   #创建一个服务器

    http_server = tornado.httpserver.HTTPServer(Application())

   #监听端口

    http_server.listen(options.port)

  #启动服务

    tornado.ioloop.IOLoop.instance().start()

 

#调用的入口

if __name__ == "__main__":

    main()

 

 最后总结一下:

1)tornado框架中提供的几个demo,都是以这种形式来创建一个应用的

2)对每一个控制器函数,要么是,只可能有2个对外的函数,一个是get,一个是post

3)数据库有3中调用方式,query,get,exec

4)获取参数的值使用 get_argument 函数

5)重定向用redirect 函数

6)所有的函数都是属性这个类的,所有都用self调用

7)渲染模板用render函数

本文转载自:http://www.cnblogs.com/yupeng/p/3362432.html

沉淀岁月
粉丝 27
博文 257
码字总数 91615
作品 0
朝阳
高级程序员
私信 提问
利用nginx做tornado的反向代理

1.tornado的demo 首先写一个tornado的demo 在生产环境中,一般使用单个的进程启动,为了简单起见,这里我们使用multiprocessing模块启动多个进程,模拟生产环境 #!/usr/bin/python --encode...

wilelm
2013/05/07
0
0
基于 Python3 和 Tornado 的博客系统 - YangBlog

YangBlog Tornado Blog Demo 地址 YangBlog 技术栈 基于 Py3 + Tornado 前端框架 Bootstrap + JQuery 富文本编辑框 bootstrap-wysiwyg 字体图标 Font Awesome 按钮 Buttons 数据库 Mysql + ......

Yanshon
2017/12/07
193
0
Python wsgiref 模块源码浅析

原文出处: 人世间(@-人世间-) 欢迎分享原创到伯乐头条 SimpleHTTPServer模块提供了创建一个http服务的例子。Python web领域里却很少这么做,而是使用了另外一个协议 — WSGI协议。Python的...

刘星石
2016/03/07
20
0
tornado—web框架基础入门

一、简介   Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务...

MK先生
2018/06/26
0
0
[原]tornado源码分析系列(一)[tornado简介]

引言: tornado是由Facebook开源的一个服务器“套装",适合于做python的web或者使用其本身提供的可扩展的功能,完成了不完整的wsgi协议,可用于做快速的web开发,封装了epoll性能较好。文章主...

长平狐
2012/11/14
845
0

没有更多内容

加载失败,请刷新页面

加载更多

将博客搬至CSDN

https://blog.csdn.net/qq_38157006

Marhal
8分钟前
1
0
unicode Java中求字符串长度length()和codePointCount()的区别

在计算字符串长度时,Java的两种方法length()和codePointCount()一度让我困惑,运行书上例子得到的长度值是相等的,那为什么要设定两个方法呢? 对于普通字符串,这两种方法得到的值是一样的...

泉天下
9分钟前
1
0
uin-app 一、学习理由

选择uni-app 理由 别人的理由 1. 5+ 有HTML5+和Native.js技术,HTML5+包含常用的跨平台的几百个API,能满足常规开发需求,而Native.js把40w原生api映 射成js对象,这样js可以直接调原生。HTM...

轻轻的往前走
10分钟前
1
0
方括号及其在命令行中的不同用法介绍

通配 方括号最简单的用法就是通配。你可能在知道“ Globbing”这个概念之前就已经通过通配来匹配内容了,列出具有相同特征的多个文件就是一个很常见的场景,例如列出所有 JPEG 文件: ls *.j...

Linux就该这么学
16分钟前
1
0
vecty 基础

gopherjs 是把 go 编译为 js 的工具。 vecty 是基于 gopherjs 的一种类似 React 的开发框架。 安装 gopherjs 和 vecty go get -u github.com/gopherjs/gopherjsgo get -u github.com/gopher......

electricface
17分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部