web框架之初识Django

  • 2019 年 12 月 16 日
  • 笔记

一、web框架

1.1什么是web框架

百度百科:Web应用框架(Web application framework)是一种开发框架,用来支持动态网站、网络应用程序及网络服务的开发。其类型有基于请求的和基于组件的两种框架。

web框架的功能其实就是网站的socket服务端中负责接收请求,并将请求分发到各功能程序,并将请求的处理结果和HTML页面返回给用户浏览器。

1.2自制的简易web框架

1.服务端接收与发送信息

这里需要说明:服务端想要与浏览器进行通信必须遵守http协议,关于http协议的介绍请参考之前的博客前端之HTML

import socket    server = socket.socket()  server.bind(('127.0.0.1', 8080))  server.listen(5)  """  请求首行  b'GET / HTTP/1.1rn  请求头  Host: 127.0.0.1:8080rn  Connection: keep-alivern  Cache-Control: max-age=0rn  Upgrade-Insecure-Requests: 1rn  User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36rn  Sec-Fetch-User: ?1rn  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3rn  Sec-Fetch-Site: nonern  Sec-Fetch-Mode: navigatern  Accept-Encoding: gzip, deflate, brrn  Accept-Language: zh-CN,zh;q=0.9rn  Cookie: csrftoken=aOZSalMQkKGbzstfjcw3O9sDoegdywL8AD7PzhidAyx3tXShN7oQtxN1MMnS6GVXrn  rn(******)  请求体  """  while True:      conn, addr = server.accept()  # 阻塞态      data = conn.recv(1024)      # print(data)      conn.send(b'HTTP/1.1 200 OKrnrn')      data_str = data.decode('utf-8')      current_path = data_str.split('rn')[0].split(' ')[1]      # print(current_path)      if current_path == '/index':          # conn.send(b'index')          with open(r'01 纯手撸的前端页面.html','rb') as f:              conn.send(f.read())      elif current_path == '/login':          conn.send(b'login')      else:          conn.send(b'404 error')      conn.close()

上面的代码只实现了简单的接收请求与发出响应的功能,关于http数据的接收与处理有专门的第三方模块。

下面我们借助第三方模块wsgiref(wsgiref模块内部封装了socket,可以将http数据封装成一个大字典,方便调用。该模块也是flask的启动源码)实现请求的处理。

from wsgiref.simple_server import make_server  from urls import urls  from views import *    def run(env,response):      """      :param env: 请求相关的所有数据 将http数据全部提前处理成了字典的形式 供调用者使用      :param response: 响应相关的所有数据      :return: 给前端真正的数据      """      # print(env)      response('200 OK',[('xxx','zgh'),])      current_path = env.get('PATH_INFO')      # print(current_path)      # if current_path == '/index':      #     return [b'index']      # elif current_path == '/login':      #     return [b'login']      # 定义一个存储函数名的标志位      func = None      for url in urls:  # url =  ('/login',login)  ('/index',index)          if current_path == url[0]:  # 用户敲的后缀名 你后端有对应的处理业务              func = url[1]  # 将匹配上的函数名赋值给func变量              break  # 一旦用户匹配上了对应的业务接口 立刻结束匹配      # 判断func是否被赋值      if func:          res = func(env)      else:          res = error(env)      return [res.encode('utf-8'),]      if __name__ == '__main__':      server = make_server('127.0.0.1',8080,run)  # 实时监听本机8080端口      # 一旦有请求来了 会统一交给run函数处理(调用run函数并传参run(env,response))      server.serve_forever()  # 启动服务端

不同的请求分发给不同的功能函数去执行

from views import *    urls = [      ('/login',login),      ('/index',index),      ('/reg',reg),      ('/xxx',xxx),      ('/get_time',get_time),      ('/get_userdict',get_userdict),      ('/get_data',get_data),  ]

功能函数,以及与数据库建立连接的函数。

def login(env):      return 'login'    def index(env):      return 'index'    def reg(env):      return 'reg'    def xxx(env):      # return 'xxx'      with open(r'templates/02 xxx.html','r',encoding='utf-8') as f:          return f.read()    def error(env):      return '404 error'      import time  def get_time(env):      ctime = time.strftime('%Y-%m-%d %X')      # 后端数据 如何传递给html页面(利用字符串的替换)      with open(r'templates/03 get_time.html','r',encoding='utf-8') as f:          data = f.read()      data = data.replace('sadadadasdsadsad',ctime)      return data      from jinja2 import Template  def get_userdict(env):      user_dic = {'username':'jason','age':18,'hobby':['read','book','run']}      with open(r'templates/04 get_user.html','r',encoding='utf-8') as f:          data = f.read()      temp = Template(data)      res = temp.render(userDic = user_dic)  # 将user_dic传递给html页面 页面上通过userDic就能够拿到后端传递过来的值      return res    import pymysql  def get_data(env):      conn = pymysql.connect(          host = '127.0.0.1',          port = 3306,          user = 'root',          password = '123qwe',          db = 'day49',          charset = 'utf8',          autocommit = True      )      cursor = conn.cursor(pymysql.cursors.DictCursor)  # 将查出来的数据组织成一个字典      sql = "select * from userinfo"  # 关键性的数据 不要自己手动拼接      affect_rows = cursor.execute(sql)  # sql注入:就是利用MySQL注释语法      # print(affect_rows)      user_list = cursor.fetchall()      # print(user_list)      # return 'hahahahha'      with open(r'templates/05 get_data.html','r',encoding='utf-8') as f:          data = f.read()      temp = Template(data)      res = temp.render(user_list = user_list)      return res

以上就是我们手撸的简易web框架仅实现了一些简单的功能,如果基于这个简单的程序进行更多功能的开发与扩展就成为了现在项目开发使用的web框架。

1.3三大主流web框架简介

Django

特点:大而全,自带的组件和功能很多,不足:写小项目的时候显得有些笨重。

Flask

特点:短小精悍,它的自带组件和功能特别少,功能的扩展完全依赖第三方组件。不足:受限于第三方模块的影响比较大,如果第三方模块加起来比Django还要大。

Tornado

基于异步非阻塞,运行速度非常快,但是与Django相比很多功能需要自己取写,随着项目越来也大,框架能够提供的功能占比也越来也小,更多的功能需要自己手动实现。

1.4动态网页与静态网页

动态网页指的是html页面获取到的数据是从后端动态获取到的;静态网页指页面上的数据是写死的。

二、初识Django框架

2.1Django的安装

2.1.1安装前的注意事项

  1. 计算机名称不能为中文
  2. python解释器不能使用3.7及更高的版本,推荐使用3.4~3.6
  3. 所有项目名称不要有中文
  4. 切记一个pycharm窗口只能运行一个pycharm项目

2.1.2关于对Django的版本

Django目前最新的版本是3.0,但是建议使用1.11(1.11.9~1.11.13)

安装方式:直接在cmd中pip3 install django==1.11.11 也可以在pycharm中的file>settings>project>Project Interface 点击右上角的加号即可搜索安装

2.1.3验证安装是否成功

在cmd中输入:django-admin

若果出现[django]相关的一堆内容则证明安装成功了。

2.1.4镜像源的切换

此处如果安装速度太慢可以切换镜像源,切换镜像源的方法如下图所示:

这里需要说明的是如果切换镜像源必须将原来的镜像源删掉,否则pycharm还会默认使用原来的镜像源。

2.2Django项目的创建与启动

1.创建Django项目

方式一:命令行键入:django-admin startproject 项目名(如mysite)

方法二:在pycharm中file>new project进入下面的界面

按照如图进行设置,第一个框是选择项目创建的路径(最好是一个空的文件夹),第二个框是template要写上,第三个框时APP的名字,写上后pycharm会自动创建一个APP。

2.创建应用的方法

在cmd键入:python manage.py startapp app01(此处是APP的名字)

pycharm中创建应用:

进入run manage以后直接输入:startapp app名称 就可以。

2.2.1两种方式创建Django项目的特点

使用pycharm创建Django项目软件会自动创建一个APP,并会创建templates文件夹,配置文件中也会帮你将templates的路径写好,也会将你的APP在配置文件中注册号,但是通过命令行创建的Django项目所有的这些步骤均需要手动去完成。(虽然命令行创建Django项目更加麻烦但是建议使用命令行的方式创建项目,因为项目在服务器上上线时使用的是命令行)。

2.2.2Django项目的启动

注意:首先必须确保同一端口只有一个项目在运行,否则启动会报错,另外酷狗音乐也会占用8000端口,默认8000端口启动时,该端口不能被占用。

方式一:命令行现将目录切换到项目目录下(cd/项目名)

然后:python3 manage.py runserver 127.0.0.1:8080这里的ip和端口可以不写,默认为8000端口。

方式二:直接点击pycharm的run按钮即可

pycharm中的ip和端口的设置:如下图所示,按照实际情况设置好ip和端口点击应用就可以了。

2.3APP的概念

APP即application应用程序,Django是一个以开发APP为主要功能的web框架,一个Django项目如同一所大学(空的架子,本身没有任何的功能)而app如同大学里面的一个个学院,app才是真正实现功能的角色。

一个项目中我们可以根据功能的不同开发多个app,每个app对应一个具体的功能模块如:用户相关的app负责用户相关的功能,订单相关的app负责订单相关的功能等。

2.3.1命令行式创建的app需要进行的配置

创建好的app需要现在Django配置文件中注册:

如图所示在settings文件里的INSTALLED_APPS里添加app的相关信息。

命令行创建的项目不会自动创建文件夹templates文件夹,需要手动创建,创建完成后在settings.py中添加templates的配置路径:DIR[os.path.join(BASE_DIR,'templates')]

2.4Django不同文件的功能

2.4.1Django项目同名的文件夹

settings.py文件:供用户使用的配置文件

urls.py:路由与视图函数的对应关系

manage.py:Django的入口文件(在项目的最外层文件)

2.4.2应用名文件夹

migrations文件夹:所有数据库相关的操作记录

admin.py:Django admin后台管理

apps.py:注册app时使用

models.py:放数据库相关的模型类

tests.py:测试文件

views.py:处理业务逻辑的视图函数

2.5Django小白必会三板斧

1.HttpResponse 返回的是字符串

2.render返回html文件,可以给html页面传值,传值方式如下所示:

def login(request):      user_dic = {'username':'xiaozhu','password':'123'}      return render(request,'login.html',{'user_info':user_dic})

3.redirect重定向

def home(request):      #return redirect('/login')如果重定向为本站的其他页面则可直接写本站其他页面的后缀      return redirect('https://www.cnblogs.com/ghylpb/')#如果重定向为其他网站则直接写其它网站的网址即可

2.6Django的重启机制

Django默认是自动重启的,重启机制是:Django会实时检测项目内部文件的变化,当检测到文件发生改变时会自动重启,也会出现我们还没有改完代码它就重启的情况,这种情况下会报错,但是我们不必理会,写完代码自己手动重启就可以了。