zoukankan      html  css  js  c++  java
  • Python Day 54 Django框架、web请求流程、状态码、自定义web框架

      ##web请求流程

    #1、软件开发架构
      c/s架构
         客户端
       服务端
      b/s架构
       浏览器
       服务器
      本质:b/s架构其实也是c/s架构
    #
    2、问题:当我们在浏览器中输入一个url地址的时候, 按下回车的那一刹那, 比如ww.baidu.com 描述一下具体的过程. 首先我们通过DNS域名解析服务器对该域名进行解析,解析顺序先找本地dns服务器,比如window系统中host文件,找不到就找根域名解析服务器,全球总共十三台,然后依次找顶级域名服务器.com、权威域名服务器baidu.com、然后二级域名服务器www,当找到www.baidu.com对应的IP地址以后,便向该服务器发送请求,服务器反馈一个响应结果 #3、Http协议介绍
      超文本传输协议:规定了客户端与服务端消息传输的格式
    #3-1、四大特性:
      1.基于TCP/IP协议作用于应用层的协议
      2.基于请求响应
      3.无状态
      4.无连接
    #3-2、数据格式之请求:
      请求首行
      请求头(一堆k,v键值对)
      
      请求体(post请求携带的数据)
    请求头: GET / HTTP/1.1 Host: 127.0.0.1:8080 (主机名) Connection: keep-alive (保持链接) Cache-Control: max-age=0 (缓存不失效) Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Token: bdsjalbdjsalbdjsa 请求体(两个换行符 后面的内容): bdsabdjsabjddas
    #3-3、数据格式之响应:
       响应首行
       响应头(一堆k,v键值对)
      
       响应体(post请求携带的数据)

    响应头: HTTP
    /1.1 200 OK 响应体: 自己看到的内容 ps: http: 默认端口是80 Https: 默认的端口是443 状态码:(*****************************
       1XX:服务器已经成功接受到你的数据正在处理,你可以继续提交其他数据 2XX:
    200 (ok)请求成功 服务器已经将你请求的数据发送给你了 3XX: 302 304重定向 4XX: 404(not found) 403(forbidden 禁止访问)请求资源不存在 5XX: 500 (服务端代码错误) 502 (网关错误 bad gateway) #4、字符串和字节的转换: >>> s = "hello" >>> s 'hello' >>> bytes(s,encoding='utf-8') b'hello' >>> b = bytes(s,encoding='utf-8') >>> str(b, encoding='utf-8')

       ##自定义web框架

    #1、需求:想要通过输入不同的 url, 获得不一样的相应内容
    #解决思路:
    #step 1、创建sokect 服务端:
        该socket服务器接收浏览器客户端发来的请求头中获取uri路径,运用了split方法取值
    
    #step 2、路由系统:
        uri 和 函数的 对应关系 :(注意自定义的原因,这里读每一个html文件都需要自己打开进行读,然后函数return进行返回)
        routes = [
            ('/xxx', f1),
        ('/ooo', f2),
            ('/hhh', f3)
        ] 
    #step 3、模板引擎渲染,显示给用户
        将html代码和mysql的数据进行手动融合,然后再替换html中自定义的内容,比如案例中自定义内容@@content@@ 
    (自己定制规则需要自己拼接格式 , 或者使用第三方的工具,比如jinjia2模块)   
      后端生成的数据直接传递给前端页面使用(并且前端页面可以灵活的操作改数据) >>> 模板语法
     
       模板渲染 模板语法需要依赖于第三方模块
       pip install jinja2
       
      templates:改文件夹存放就是所有的页面文件(.html)

       模板语法  jinja2支持前端直接使用类似于python的语法操作数据
       <p>{{ user_dic }}</p>
       <p>{{ user_dic.name }}</p>
       <p>{{ user_dic['password'] }}</p>
       <p>{{ user_dic.get('name') }}</p>
     
       {% for user in user_dict %}  <!--[{},{},{},{}]-->
        <tr>
           <td>{{ user.id }}</td>
           <td>{{ user.name }}</td>
           <td>{{ user.password }}</td>
        </tr>
       {% endfor %}
    #案例 *****自定制server.py***** import socket import time def f1(): fp = open('index.html','r',encoding='utf-8') data = fp.read() fp.close() return bytes(data,encoding='utf-8') def f2(): fp = open('article.html','r',encoding='utf-8') data = fp.read() ctime = time.time() data = data.replace('@@content@@',str(ctime)) return bytes(data, encoding='utf-8') def f3(): import pymysql conn = pymysql.connect(host='127.0.0.1',user='root',password='123',db='db1',charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select id,name,depart_id from userinfo' cursor.execute(sql) res = cursor.fetchall() print(res) res_list = [] for user in res: res_str = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>"%(user["id"],user['name'],user["depart_id"]) res_list.append(res_str) s="".join(res_list) fp = open('content.html','r',encoding='utf-8') data = fp.read() fp.close() data = data.replace("@@content@@", s) return bytes(data,encoding='utf-8') def f4(): import pymysql conn = pymysql.connect(host='127.0.0.1',user='root',password='123',db='db1',charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select id,name,depart_id from userinfo' cursor.execute(sql) users = cursor.fetchall() # print(res) fp = open('content-jinjia2.html','r',encoding='utf-8') data = fp.read() fp.close() from jinja2 import Template template = Template(data) data = template.render(users = users) return bytes(data,encoding='utf-8') routers = ( ('/ooo',f1), ('/xxx',f2), ('/hhh',f3), ('/kkk',f4) ) def run(): server = socket.socket() server.bind(("127.0.0.1",1688)) server.listen(5) while True: client,addr = server.accept() buf = client.recv(1024) data = str(buf,encoding='utf-8') header_list = data.split(' ')[0].split(' ')[0] uri = header_list.split(' ')[1] #第一种方式:缺点:扩展性差 # res = None # if uri == '/xxx': # res = bytes("this is xxx",encoding='utf-8') # elif uri == '/ooo': # res = bytes("this is ooo", encoding='utf-8') # else: # res = bytes('404 not fund',encoding='utf-8') #第二种:路由方式 func_name = None for item in routers: if uri == item[0]: func_name = item[1] break if func_name: res = func_name() else: res = b'404 not fund' client.send(bytes('HTTP/1.1 200 OK ',encoding='utf-8')) client.send(res) client.close() if __name__ == '__main__': run() *************index.html 静态显示********** <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>this is index</h1> </body> </html> ***********article.html 可以替换自定义内容动态显示时间********** <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> @@content@@ </body> </html> *********content.html 可以替换自定义显示内容********* <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1px"> <thead> <tr> <th>ID</th> <th>Name</th> <th>department_id</th> </tr> </thead> <tbody> @@content@@ </tbody> </table> </body> </html> *********content-jinjia2.html使用第三方工具渲染********* <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1px"> <thead> <tr> <th>ID</th> <th>Name</th> <th>department_id</th> </tr> </thead> <tbody> {%for item in users%} <tr> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.depart_id}}</td> </tr> {%endfor%} </tbody> </table> </body> </html>
    #2、web框架分类:
      a. sokect 服务端 b、路由系统 c、模板引擎渲染
      
     第一种维度分类:
      - a,b,c  ----> tornado
      - a(用第三方), b, c ----> django wsgiref  uwsgi
      - a(第三方),b, c(第三方) -----》 flask 

     注:
      
       web服务网关接口
             WSGI协议
             wsgiref(django自带的 可承受的并发量不是很高 通常指用于本地测试)
             uwsgi  (django项目上线之后会使用)
             werkzeug (flask使用的)
            实现WSGI协议的功能模块
            ps:
              请求来的时候处理http格式的数据
              请求走的时候讲后端发送的数据打包成符合http格式的数据再发送
     


    python三大主流web框架
     Django:大而全,自带了很多功能模块,类似于航空母舰 (缺点:有点笨重)
     Flask:短小精悍,自带的功能模块特别少,大部分都是依赖于第三方模块(小而轻)
     Tornado:异步非阻塞 主要用在处理高io 多路复用的情况 可以写游戏后端
     
     第二种维度:
      
      - django
      - 其他

       

      ##Django基础

    #1、安装:
        pip3 install django==1.11.10 -i https://pypi.tuna.tsinghua.edu.cn/simple 
    
    
    #2、创建:
        创建django项目的方式
          方式1(命令行创建):
             创建django项目
                django-admin startproject 项目名
             创建app应用
                python3 manage.py startapp app01
             启动django项目
                python3 manage.py runserver
             ps:用命令行创建django默认不会自动创建templates文件夹
             需要你手动自己创建(注意改文件夹路径是否被添加配置文件中)
           方式2(pycharm创建)
             FILE >>> new project 选择第二个django 需要注意名字不能有中文,选择本地的解释器,勾选后台管理
             创建app
                pycharm命令行创建
                   python3 manage.py startapp app01
                Tools下面run manage task功能栏
             启动点小绿色箭头
       
      
      强调:
         1.用django一定要保证只有一个在运行状态  切记切记!!!!!!!
         2.一定记得清浏览器的缓存
      
      app(应用)的概念
         一个django项目就是一所大学
         app就是大学里面的学院
      注意新创建的app需要在配置文件中注册才能生效(*******************)
        INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
         'app01.apps.App01Config'  # 可以用全称
         'app01'      # 也可以简写
      ]
    #3、目录介绍: 应用名
         migrations  数据库迁移记录相关数据
         admin.py    django后台管理相关
         models.py   模型表相关
         views.py    视图函数相关 mysite: mysite项目名: settings.py : 用户自定义的各种配置 urls.py : 路由与视图含书映射关系 wsgi.py : 启动socket服务端的 文件 mange.py: django入口文件、 管理文件、 python mange.py 各种命令
         templates:项目用到的所有的html文件 js, css, img : 静态 文件
    #4、以后创建django完成之后: a. 配置末班文件路径: 'DIRS': [os.path.join(BASE_DIR, 'templates')] b. 配置静态资源的文件路径: STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), (逗号不能少) ) c. 注释中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
    #5、写业务逻辑的话:
        
        uri和函数的对应关系:
         urlpatterns = [
          # url(r'^admin/', admin.site.urls),
          url(r'^index/', index),
         ]
        
        业务逻辑函数:
        
         def index(request):
          return render(request, "index.html")

       ##Django + 前端表单提交数据到后台

    #django小白必会三板斧
    #
    HttpResponse:它是作用是内部传入一个字符串参数,然后发给浏览器。 # render:render方法可接收三个参数,一是request参数,二是待渲染的html模板文件,三是保存具体数据的字典参数。 它的作用就是将数据填充进模板文件,最后把结果返回给浏览器。与jinja2类似。 #redirect   重定向 又走了一次网络请求 注意:django必会三板斧返回的都是HttpReponse对象
    #1、创建一个Django项目(功能:数据库验证登录、登陆失败标红从新渲染、登陆成功跳转) #1-1、完成三件事(上述有讲解 ,此处省略) #1-2、路由文件urls.py中 添加路由 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',index), url(r'^login/',login), ] 创建相对应函数 def index(request): return render( request, 'index.html', { "username":"icon", "mylist":["icon",'is','18'], "mydict":{"name":"icon","age":"18"}, "userinfo":[ {"name":"icon1","age":"18","sex":"male"}, {"name":"icon2","age":"19","sex":"male"}, {"name":"icon3","age":"20","sex":"male"}, {"name":"icon4","age":"21","sex":"male"}, ] }, ) def login(request): if request.method == 'GET': return render(request,'login.html') else: import pymysql conn = pymysql.connect(host='127.0.0.1', user='root', password='123', db='db1', charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select * from user' cursor.execute(sql) # 数据库数据列表套字典 users = cursor.fetchall() #前端传过来的用户信息和密码 username = request.POST.get('username') password = request.POST.get('password') for user in users: if username == user.get('username') and password == user.get('password'): return HttpResponseRedirect("/index/") return render(request,'login.html',{'error_msg':'用户名或密码错误'}) #1-3、在templates目录创建index.html文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#1、渲染:变量替换,替换的key必须和urls.py文件中一一对应#} {{ username }} <hr> {#2、渲染:列表替换#} {#{{ mylist.0 }}#} {#{{ mylist.1 }}#} {#{{ mylist.2 }}#} <ul> <li>{{ mylist.0 }}</li> <li>{{ mylist.1 }}</li> <li>{{ mylist.2 }}</li> </ul> <hr> {#3、渲染:列表循环替换#} <ul> {% for item in mylist %} <li> {{ item }} </li> {% endfor %} </ul> <hr> {#4、渲染:字典循环替换显示给用户#} {% for key,val in mydict.items %} <li> {{ key }} --- {{ val }} </li> {% endfor %} <hr> {% for key in mydict.keys %} <li> {{ key }} </li> {% endfor %} <hr> {#5、渲染:表格#} <table border="1px"> <thead> <tr> <th>name</th> <th>age</th> <th>sex</th> </tr> </thead> <tbody> {% for user in userinfo %} <tr> <td>{{ user.name }}</td> <td>{{ user.age }}</td> <td>{{ user.sex }}</td> </tr> {% endfor %} </tbody> </table> </body> </html> #1-4、在templates目录创建login.html文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {# <link rel="stylesheet" href="../bootstrap-3.3.7-dist/css/bootstrap.css">#} </head> <body> <form action="/index/" method="post"> 用户名:<input type="text" name="username" ><br> 密码:<input type="password" name="password"> <i style="color: red;">{{ error_msg }}</i><br> <input type="submit" value="登录"> </form> </body> {#<script src="../js/jquery-3.4.1.js"></script>#} {#<script src="../bootstrap-3.3.7-dist/js/bootstrap.js"></script>#} </html>
  • 相关阅读:
    进制转化
    递归小结
    Java异常处理面试题归纳
    字符串相加 内存分配
    递归与循环
    cookie
    会话管理
    在javaweb中通过servlet类和普通类读取资源文件
    JS中遍历EL表达式中后台传过来的Java集合
    Ztree加载完成后显示勾选节点
  • 原文地址:https://www.cnblogs.com/liangzhenghong/p/11158131.html
Copyright © 2011-2022 走看看