精华内容
参与话题
问答
  • web框架

    千次阅读 2020-01-04 19:20:55
    Web框架 Flask Django Tornado Twisted ODOO

    Web框架

    • Flask
    • Django
    • Tornado
    • Twisted
    • ODOO

    在这里插入图片描述

    展开全文
  • web服务器和web框架的作用及其关系

    千次阅读 多人点赞 2018-10-15 21:24:27
    web服务器和web框架的作用及其关系 1.web服务器作用: 1)解析请求报文,调用框架程序处理请求。 2)组织响应报文,返回内容给客户端。 2.web框架程序的作用: 1)路由分发(根据url找到对应的处理函数) 。 2)在处理...

    web服务器和web框架的作用及其关系
    1.web服务器作用:
    1)解析请求报文,调用框架程序处理请求。
    2)组织响应报文,返回内容给客户端。
    2.web框架程序的作用:
    1)路由分发(根据url找到对应的处理函数) 。
    2)在处理函数中进行业务的处理。
    服务器和客户端之间的连接靠web服务器来维持,web服务器接收到请求后,将请求以及相关的参数传递给web框架,由框架负责生成内容,并将生成的内容传递给web服务器。所以web服务器的职责是接受并返回请求,web服务器的职责是内容生成服务器和客户端之间的连接靠web服务器来维持,web服务器接收到请求后,将请求以及相关的参数传递给web框架,由框架负责生成内容,并将生成的内容传递给web服务器。所以web服务器的职责是接受并返回请求,web服务器的职责是内容生成

    展开全文
  • [33]python Web 框架:Tornado

    万次阅读 多人点赞 2018-06-10 00:08:59
    轻量级web框架 异步非阻塞IO处理方式 出色的抗负载能力 优异的处理性能,不依赖多进程/多线程,一定程度上解决C10K问题 WSGI全栈替代产品,推荐同时使用其web框架和HTTP服务器 1.2.Tornado VS Djang...

    1.Tornado

    • Tornado:python编写的web服务器兼web应用框架

    1.1.Tornado的优势

    • 轻量级web框架
    • 异步非阻塞IO处理方式
    • 出色的抗负载能力
    • 优异的处理性能,不依赖多进程/多线程,一定程度上解决C10K问题
    • WSGI全栈替代产品,推荐同时使用其web框架和HTTP服务器

    1.2.Tornado VS Django

    • Django:重量级web框架,功能大而全,注重高效开发
    • 内置管理后台
    • 内置封装完善的ORM操作
    • session功能
    • 后台管理
    • 缺陷:高耦合
    • Tornado:轻量级web框架,功能少而精,注重性能优越
    • HTTP服务器
    • 异步编程
    • WebSocket
    • 缺陷:入门门槛较高

    2.安装

    输入命令:

    pip install tornado
    

    备注:
    Tornado应该运行在类Unix平台,为了达到最佳的性能和扩展性,仅推荐Linux和BSD(充分利用Linux的epoll工具和BSD的kqueue达到高性能处理的目的)

    3.使用

    3.1.Tornado入门程序 - (一)

    #-*- coding:utf-8 -*-
    import tornado.web
    import tornado.ioloop
    
    
    #定义处理类型
    class IndexHandler(tornado.web.RequestHandler):
        #添加一个处理get请求方式的方法
        def get(self):
            #向响应中,添加数据
            self.write('好看的皮囊千篇一律,有趣的灵魂万里挑一。')
    
    if __name__ == '__main__':
        #创建一个应用对象
        app = tornado.web.Application([(r'/',IndexHandler)])
        #绑定一个监听端口
        app.listen(8888)
        #启动web程序,开始监听端口的连接
        tornado.ioloop.IOLoop.current().start()
    

    1 .在pycharm中直接运行代码
    2 .如果是在ubuntu,在命令窗口输入

    python 文件名.py
    

    使用浏览器访问

    4.Tornado 代码解析

    4.1.入门程序代码解析

    • tornado.web:tornado的基础web框架

      • RequestHandler:封装对请求处理的所有信息和处理方法
      • get/post/..:封装对应的请求方式
      • write():封装响应信息,写响应信息的一个方法
    • tornado.ioloop:核心io循环模块,封装linux的epoll和BSD的kqueue, tornado高性能处理的核心。

      • current()返回当前线程的IOLoop实例对象
      • start()启动IOLoop实力对象的IO循环,开启监听

    4.2.httpserver底层处理

    • httpserver监听端口
    tornado.httpserver.HTTPServer(app)
    httpserver.listen(port)
    
    • httpserver实现多进程操作
    tornado.httpserver.HTTPServer(app)
    httpserver.bind(port)
    httpserver.start(0/None/<0/num)
    
    # -*- coding:utf-8 -*-
    from tornado.web import Application,RequestHandler
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    
    class IndexHandler(RequestHandler):
        def get(self):
            self.write('给自己一点时间,理清所有的荒唐与期望。')
    
    if __name__ == '__main__':
        app = Application([(r'/',IndexHandler)])
        http_server = HTTPServer(app)
        #最原始的方式
        http_server.bind(8888)
        http_server.start(1)
    
        #启动Ioloop轮循监听
        IOLoop.current().start()
    

    同时打开两个窗口测试发现实现了多进程

    4.3.options配置

    • 全局配置
    tornado.options.define(
        name, default, type, multiple, help
    )
    
    • 命令行参数转换
    tornado.options.parse_command_line()
    
    #-*- coding:utf-8 -*-
    
    from tornado.web import RequestHandler,Application
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    import tornado.options
    
    #定义变量
    tornado.options.define('port',default=8000,type=int,help="this is the port >for application")
    
    class IndexHandler(RequestHandler):
       def get(self):
           self.write('我们既然改变不了规则,那就做到最好')
    
    if __name__ == '__main__':
       app = Application([(r'/',IndexHandler)])
       tornado.options.parse_command_line()
    
       http_server = HTTPServer(app)
       http_server.bind(tornado.options.options.port)
       http_server.start(1)
       #启动IOLoop轮循监听
       IOLoop.current().start()
    

    通过命令窗口输入port来访问
    通过使用我们命令窗口设定的port进行访问

    • 配置文件
    #即在当前py文件目录创建config文件,并在py代码中加入以下代码,
    tornado.options.parse_config_file("./config")
    
    • 配置模块:跟配置文件类似

    4.4.application配置

    • 程序调试之debug配置
    #自动重启+取消缓存模板+取消缓存静态文件+提供追踪信息
    tornado.web.Application([(..)], debug=True)
    
    注:开发之初可以设置debug=True方便调试,开发完毕改为False.
    
    • 路由信息初始化参数配置
    tonado.web.Application([(r””, Handler, {k:v})])
    def initialize(self, k)
    
    • 路由名称设置及反解析
    #名称设置
    tornado.web.Application([
        url(r””, handler, {k,v}, name=“”)
    ])
    
    #反解析操作
    reverse_url(name)
    

    实例

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler, url
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            self.write("<a href='"+self.reverse_url("login")+"'>用户登录</a>")
    
    
    class RegistHandler(RequestHandler):
        def initialize(self, title):
            self.title = title
    
        def get(self):
            self.write("注册业务处理:" + str(self.title))
    
    
    class LoginHandler(RequestHandler):
        def get(self):
            self.write("用户登录页面展示")
    
        def post(self):
            self.write("用户登录功能处理")
    
    
    if __name__ == "__main__":
        app = Application(
            [
                (r"/", IndexHandler),
                (r"/regist", RegistHandler, {"title": "会员注册"}),
                url(r"/login", LoginHandler, name="login"),
            ]
        )
    
        http_server = HTTPServer(app)
        http_server.listen(8000)
    
        IOLoop.current().start()
    

    4.5.参数传递

    • get方式传递参数
    get_query_arguments(name,default=_ARG_DEFAULT,strip=True)
    get_query_argument(name ,strip=True)
    
    • post方式传递参数
    get_body_arguments(name, default=_ARG_DEFAULT,strip=True)
    get_body_argument(name ,strip=True)
    

    实例

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            # 获取get方式传递的参数
            username = self.get_query_argument("username")
            usernames = self.get_query_arguments("username")
    
            print (username)
            print (usernames)
    
        def post(self):
            # 获取post方式传递的参数
            username = self.get_body_argument("username")
            usernames = self.get_body_arguments("username")
    
            print (username)
            print (usernames)
    
    if __name__ == "__main__":
        app = Application([(r"/",IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    
    #网页运行时需要传入参数
    #192.168.11.79:8000/?username=123
    
    • 混合方式
    get_arguments(..)/get_argument(..)
    

    实例

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            # 获取get方式的参数
            user = self.get_argument("user")
            print("get方式获取参数:" + str(user))
    
        def post(self):
            # 获取post方式的参数
            user = self.get_argument("user")
            print("post方式获取参数:" + user.encode("utf-8"))
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    
    • 其他参数
    通过request获取参数数据
    method/host/uri/path/query/version/headers/body/remote_ip/files
    

    实例

    • request/json
    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
        def get(self):
            print self.request
    
            json_str = {"username": "admin", "password": "123123"}
            self.write(json.dumps(json_str))
    
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    
    • header
    • .add_header() .set_header() .set_default_headers()
      • 设置响应HTTP头, 前两者的不同点在于多次设置同一个项时, .add_header()叠加参数, 而.set_header()则以最后一次为准.
      • .set_default_headers()比较特殊, 是一个空方法, 可根据需要重写, 作用是在每次请求初始化RequestHandler时设置默认headers.
    • .clear_header() .clear()
      • .clear_header()清除指定的headers, 而.clear()清除.set_default_headers()以外所有的headers设置.
    # add_header
    self.add_header('Foo', 'one')
    self.add_header('Foo', 'two')
    # set_header
    self.set_header('Bar', 'one')
    self.set_header('Bar', 'two')
    
    # HTTP头的设置结果
    # Foo → one, two
    # Bar → two
    
    

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
        def set_default_headers(self):
            # 第二种响应头设置方式
            print("---------> 响应头set_default_headers()执行")
            self.set_header("Content-type", "application/json; charset=utf-8")
            self.set_header("qiku", "奇酷信息")
    
        def get(self):
            # 第一种操作响应头的方式:
            # self.set_header("Content-type", "application/json")
            print("---------->get方法执行")
            self.write("{'name':'jerry'}")
            self.set_header("qiku", "qikuedu.com")
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    
    • writerror
      • .send_error()用于发送HTTP错误页(状态码). 该操作会调用.clear() .set_status()
      • .write_error()用于清除headers, 设置状态码, 发送错误页. 重写.write_error()可以自定义错误页.
    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            self.write("hello qikuedu.com")
    
            self.send_error(404, msg="页面丢失", info="家里服务器搞对象去了")
    
        def write_error(self, status_code, **kwargs):
            self.write("<h1>出错啦,工程师MM正在赶来的途中...</h1>")
            self.write("<p>错误信息:%s</p>" % kwargs["msg"])
            self.write("<p>错误描述:%s</p>" % kwargs["info"])
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    

    数据流

    • .write()

      • 将数据写入输出缓冲区. 如果直接传入dict, 那Tornado会自动将其识别为json, 并把Content-Type设置为application/json, 如果你不想要这个Content-Type, 那么在.write()之后, 调用.set_header()重新设置就好了. 需要注意的是, 如果直接传入的是list, 考虑到安全问题(json数组会被认为是一段可执行的JavaScript脚本, 且<script src="*/secret.json">可以绕过跨站限制),list将不会被转换成json.
    • .flush()

      • 将输出缓冲区的数据写入socket. 如果设置了callback, 会在完成数据写入后回调. 需要注意的是, 同一时间只能有一个"等待"的flush callback, 如果"上一次"的flush callback还没执行, 又来了新的flush, 那么"上一次"的flush callback会被忽略掉.
    • .finish()

      • 完成响应, 结束本次请求. 通常情况下, 请求会在return时自动调用.finish(), 只有在使用了异步装饰器@asynchronous或其他将._auto_finish设置为False的操作, 才需要手动调用.finish().
    • cookie

    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler
    from tornado.ioloop import IOLoop
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            self.write("hello qikuedu.com")
    
            self.set_cookie("loginuser", "admin老王")
    
            print self.get_cookie("loginuser")
    
            print self.cookies
    
    
    if __name__ == "__main__":
        app = Application([(r"/", IndexHandler)])
    
        app.listen(8000)
    
        IOLoop.current().start()
    

    页面

    • .render()

      • 返回渲染完成的html. 调用后不能再进行输出操作.
    • .redirect()

      • 重定向, 可以指定3xx重定向状态码. 调用后不能再进行输出操作.
    # 临时重定向 301
    self.redirect('/foo')
    # 永久重定向 302
    self.redirect('/foo', permanent=True)
    # 指定状态码, 会忽略参数 permanent
    self.redirect('/foo', status=304)
    
    • redirect
    # -*- coding:utf-8 -*-
    
    from tornado.web import Application, RequestHandler, url
    from tornado.ioloop import IOLoop
    from tornado.httpserver import HTTPServer
    
    
    class IndexHandler(RequestHandler):
    
        def get(self):
            self.write("<a href='"+self.reverse_url("login")+"'>用户登录</a>")
    
    
    class RegistHandler(RequestHandler):
        def initialize(self, title):
            self.title = title
    
        def get(self):
            self.write("注册业务处理:" + str(self.title))
    
    
    class LoginHandler(RequestHandler):
        def get(self):
            self.write("用户登录页面展示")
    
        def post(self):
            self.write("用户登录功能处理")
    
    
    if __name__ == "__main__":
        app = Application(
            [
                (r"/", IndexHandler),
                (r"/regist", RegistHandler, {"title": "会员注册"}),
                url(r"/login", LoginHandler, name="login"),
            ]
        )
    
        http_server = HTTPServer(app)
        http_server.listen(8000)
    
        IOLoop.current().start()
    
    展开全文
  • Python进阶(三十六)-Web框架Django项目搭建全过程

    万次阅读 多人点赞 2017-04-15 08:53:16
    Python Web框架Django项目搭建全过程   IDE说明: Win7系统 Python:3.5 Django:1.10 Pymysql:0.7.10 Mysql:5.5   Django 是由 Python 开发的一个免费的开源网站框架,可以用于快速搭建高性能,优雅的网站!...

    #Python进阶(三十六)-Web框架Django项目搭建全过程
      IDE说明:

    • Win7系统

    • Python:3.5

    • Django:1.10

    • Pymysql:0.7.10

    • Mysql:5.5
      注:可通过pip freeze查看已安装库版本信息。
      Django 是由 Python 开发的一个免费的开源网站框架,可以用于快速搭建高性能,优雅的网站!
      ##Django 特点

    • 强大的数据库功能

    • 用python的类继承,几行代码就可以拥有一个丰富,动态的数据库操作接口(API),如果需要你也能执行SQL语句。

    • 自带的强大的后台功能

    • 几行简单的代码就让你的网站拥有一个强大的后台,轻松管理你的内容! 优雅的网址

    • 用正则匹配网址,传递到对应函数,随意定义,如你所想!

    • 模板系统–强大,易扩展的模板系统,设计简易,代码,样式分开设计,更容易管理。

    • 缓存系统–与memcached或其它的缓存系统联用,更出色的表现,更快的加载速度。

    • 国际化–完全支持多语言应用,允许你定义翻译的字符,轻松翻译成不同国家的语言。

      有关Python,Mysql的安装操作这里不再进行阐述,大家可在网络上自行查找解决。其中,django,pymysql的安装使用pip install *命令即可完成。
      安装好Django之后, 就可以使用 django-admin.py管理工具来创建一个项目。首先我们来看下django-admin.py的命令介绍,在命令行输入django-admin.py查看可用的项目管理命令。
    这里写图片描述
      Django项目创建HelloWorld项目具体过程如下:
      Step1: 在搭建Django项目之前,首先选择项目存放目录。然后在Dos窗口CD切换到项目存放目录。
      Step2: 创建项目 执行django-admin.py startproject HelloWorld
      打开IDEA,可看到创建的项目目录如下图所示:
    这里写图片描述
      目录说明:

    • HelloWorld: 项目的容器。
    • manage.py: 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。
    • HelloWorld/init.py: 一个空文件,告诉 Python 该目录是一个 Python 包。
    • HelloWorld/settings.py: 该 Django 项目的设置/配置。
    • HelloWorld/urls.py: 该 Django 项目的 URL 声明; 一份由 Django 驱动的网站"目录"。
    • HelloWorld/wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目。

      接下来我们进入 HelloWorld 目录输入以下命令,启动服务器:

    python manage.py runserver 0.0.0.0:8000
    

      0.0.0.0 让其它电脑可连接到开发服务器,8000 为端口号。如果不说明,那么端口号默认为 8000。
      在浏览器输入你服务器的ip及端口号,如果正常启动,输出结果如下:
    这里写图片描述
      Step3: 创建应用 在命令行输入django-admin.py startapp demo
      打开IDEA,可看到创建的项目目录如下图所示:
    这里写图片描述
      目录说明:

    • demo: 应用的容器。注:后面的页面设计文件,在此目录下创建目录templates,名为XX.html的文件放在此处。
    • init.py:如上一个__init__.py文件
    • migrations: 数据库相关目录,同步数据库之后会出现数据类。
    • admin.py: admin后台管理文件
    • apps.py: app应用管理文件
    • models.py:主要用一个 Python 类来描述数据表,称为模型(model) 。运用这个类,你可以通过简单的 Python的代码来创建、检索、更新、删除 数据库中的记录而无需写一条又一条的SQL语句。
    • tests.py:测试文件
    • views.py:包含了页面的业务逻辑。
      ##创建超级管理员
    python manage.py createsuperuser
     
    # 按照提示输入用户名和对应的密码就好了邮箱可以留空,用户名和密码必填
     
    # 修改 用户密码可以用:
    python manage.py changepassword username
    

    ##附
    ###服务端响应客户端请求过程
      流程图如下:
    这里写图片描述
      上面的流程图可以大致描述Django处理request的流程,按照流程图2的标注,可以分为以下几个步骤:

    • 1.用户通过浏览器请求一个页面。
    • 2.请求到达Request Middlewares,中间件对request做一些预处理或者直接response请求。
    • 3.URLConf通过urls.py文件和请求的URL找到相应的View。
    • 4.View Middlewares被访问,它同样可以对request做一些处理或者直接返回response。
    • 5.调用View中的函数。
    • 6.View中的方法可以选择性的通过Models访问底层的数据。
    • 7.所有的Model-to-DB的交互都是通过manager完成的。
    • 8.如果需要,Views可以使用一个特殊的Context。
    • 9.Context被传给Template用来生成页面。
    • a.Template使用Filters和Tags去渲染输出
    • b.输出被返回到View
    • c.HTTPResponse被发送到Response Middlewares
    • d.任何Response Middlewares都可以丰富response或者返回一个完全不同的response
    • e.Response返回到浏览器,呈现给用户

    ###url() 函数
      Django url() 可以接收四个参数,分别是两个必选参数:regex、view 和两个可选参数:kwargs、name,接下来详细介绍这四个参数。

    • regex: 正则表达式,与之匹配的 URL 会执行对应的第二个参数 view。
    • view: 用于执行与正则表达式匹配的 URL 请求。
    • kwargs: 视图使用的字典类型的参数。
    • name: 用来反向获取 URL。

    ##Django项目部署
      在前面的介绍中我们使用 python manage.py runserver 来运行服务器。这只适用测试环境中使用。
      正式发布的服务,我们需要一个可以稳定而持续的服务器,比如apache, Nginx, lighttpd等,本文后续将以 Nginx 为例。
    ##设置用自己的iP地址访问项目

    • 1.首先需要执行>manage.py runserver 0.0.0.0:8000。
    • 2.在setting.py里面需要添加ALLOWED_HOSTS="*"。

    ##学习资料
      http://www.ziqiangxuetang.com/django/django-tutorial.html

    ![这里写图片描述](https://img-blog.csdnimg.cn/img_convert/46cc348062c27bf57424afe162b04ab4.png) ![这里写图片描述](https://img-blog.csdnimg.cn/img_convert/f9c024e20306fb0e4e3e84a15aab3217.png)
    展开全文
  • 最好的6个Go语言Web框架

    万次阅读 多人点赞 2017-12-07 14:26:37
    原文:Top 6 web ...以下为译文:GO 语言爱好者的最佳Web框架如果你是自己写一个小应用程序,那你可能不需要Web框架。但是如果你要做产品,那么你肯定需要一个好的框架。如果你认为你有相应的知识和经验,你会
  • 下面为大家简单的介绍一下Web框架的基本内容,希望对大家有帮助。 Web框架(Web framework)或者叫做Web应用框架(Web application framework),是用于进行Web开发的一套软件架构。大多数的Web框架提供了一套开发和部署...
  • 什么是web框架
  • 轻量级的Web框架Gin教程

    千人学习 2019-02-08 20:29:33
    Gin 是一个 go 写的 web 框架,封装比较优雅,API友好,源码注释比较明确,具有高性能的优点。 Golang的高并发一大利器就是协程。Gin里可以借助协程实现异步任务。
  • 异步Web框架全面比较

    千次阅读 2019-04-11 09:38:39
    Node.js是开发web后端的最佳选择。它用于构建快速,可伸缩的服务器端Web应用程序。...目前最强的web后端框架仍然是Express,但是我很担心以后express会变成所谓的“经典的框架‘或者”传统web框架“,因为一旦...
  • python web框架 - Django

    千次阅读 2014-03-23 16:30:13
    Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。 Django是一个开放源代码的Web应用框架,由Python写成。Django遵守BSD版权,初次发布于2005年7月, 并...
  • 2015年Web框架评测

    千次阅读 2015-04-29 13:13:18
    2015年Web框架评测国外的TechEmpower公司今年再次发布了2015年Web框架评测报告。2014年的报告见:http://www.infoq.com/news/2014/05/benchmark-web-framework,2013年的报告见:...
  • web服务器与web框架

    千次阅读 2019-01-17 10:02:31
    Web 服务器 当我们在浏览器输入URL后,浏览器会先请求DNS服务器,获得请求站点的 IP 地址。然后发送一个HTTP Request(请求)给拥有该 IP 的主机,接着就会接收到服务器给我们的 HTTP Response(响应),浏览器经过...
  • 快速开发一个 Web 框架

    千次阅读 2018-07-28 23:30:01
    怎么使用 Node.js 开发一个属于自己的 Web 框架呢?下面我将带领大家在 Koa2 的基础上开发一款初步具备 Web 功能的框架。 本场 Chat 主要内容: Web 框架需要那些功能。 完成一个简单的框架雏形。 添砖加瓦,构成一...

空空如也

1 2 3 4 5 ... 20
收藏数 135,308
精华内容 54,123
关键字:

web框架