学习Django的之前先回顾一下软件开发架构知识
软件开发架构和WEB框架
架构:
C/S架构
B/S架构(本质也是C/S)
WEB框架:
HTTP协议
"""
网络协议 数据展示方式
HTTP协议 数据传输是明文
HTTPS协议 数据传输是密文
websocket协议 数据传输是密文
四大特性
1.基于请求响应
2.基于TCP、IP作用于应用层之上的协议
3.无状态
4.短/无链接
数据格式
请求首行(HTTP协议版本 请求方式) 响应首行(HTTP协议版本 状态码)
请求头(key:value键值对) 响应头(key:value键值对)
请求体(向服务器提交的数据) 响应体(展示给用户的数据)
响应状态码
1XX:服务器接收数据正在处理,可继续提交其它数据
2XX:响应成功 200 OK
3XX:请求重定向
4XX:页面请求错误 403没有权限 404请求不合法,请求资源不存在
5XX:服务器内部错误 500
"""
手撸模拟WEB框架(基础版)
web框架其实就是前端页面和后端服务的交互,可以将web框架理解成服务端
import socket server = socket.socket() # TCP 三次握手四次挥手 osi七层 server.bind(('127.0.0.1',8080)) # IP协议 以太网协议 arp协议... server.listen(5) # 池 进程池 线程池 while True: conn, addr = server.accept() data = conn.recv(1024) # print(data) # 二进制数据 data = data.decode('utf-8') # 字符串 # 获取字符串中特定的内容 正则 如果字符串有规律也可以考虑用切割 conn.send(b'HTTP/1.1 200 OK ') # 固定格式 current_path = data.split(' ')[1] # 获取到用户输入的网址后缀 # print(current_path) if current_path == '/index': # conn.send(b'index heiheihei') with open(r'templates/01 myhtml.html', 'rb') as f: conn.send(f.read()) elif current_path == '/login': conn.send(b'login') else: # 直接忽略favicon.ico conn.send(b'hello web') conn.close() # 前端页面链接返回的data二进制数据 """ b'GET / HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 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;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: csrftoken=KYJnVBLPpJxwt09TOmTXzpb5qkFJwHVxVGpi0NxEGIg4z5VUuazZ1O2RMwSisu14 ' """
注意:
纯手写的不足:
1.所有人都要重复的写服务端代码
2.手动处理HTTP格式数据,只能拿到url后缀,想获取其它数据较为繁琐(数据格式一样处理的代码其实也大致一样 重复写)
3.并发问题(不能实现多并发)
wsgiref模块
wsgiref模块
1.请求来的时候解析http格式的数据 封装成大字典
2.响应走的时候给数据打包成符合http格式 再返回给浏览器
借助wsgiref模块改进上面web框架(如上图框架)
""" urls.py 路由与视图函数对应关系 views.py 视图函数(后端业务逻辑) templates文件夹 专门用来存储html文件 """ # 按照功能的不同拆分之后 后续添加功能只需要在urls.py书写对应关系然后取views.py书写业务逻辑即可
************下面是服务端代码**************
from wsgiref.simple_server import make_server from urls import urls from views import * def run(env, response): """ :param env:请求相关的所有数据 :param response:响应相关的所有数据 :return: 返回给浏览器的数据 """ # print(env) # 大字典 wsgiref模块帮你处理好http格式的数据 封装成了字典让你更加方便的操作 # 从env中取 response('200 OK', []) # 响应首行 响应头 current_path = env.get('PATH_INFO') # if current_path == '/index': #方式一 # return [b'index'] # elif current_path == '/login': # return [b'login'] # return [b'404 error'] # 定义一个变量 存储匹配到的函数名 func = None for url in urls: # url (),() #方式二 if current_path == url[0]: # 将url对应的函数名赋值给func func = url[1] break # 匹配到一个之后 应该立刻结束for循环 # 判断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) """ 会实时监听127.0.0.1:8080地址 只要有客户端来了 都会交给run函数处理(加括号触发run函数的运行) flask启动源码 make_server('127.0.0.1',8080,obj) __call__方法 """ server.serve_forever() # 启动服务端
urls.py代码
from day59.views import * # url与函数对应关系 urls = [ ('/index', index), ('/login', login), ('/get_date',get_date), ('/get_dict',get_dict), ('/get_table',get_table) ]
views.py代码
# 主页 def index(env): pass # 登录页面 def login(env): with open(r'templates/01 login.html', 'r', encoding='utf8') as f: data = f.read() return data # 自定义404页面返回 def error(env): with open(r'templates/error404.html', 'r', encoding='utf8') as f: date = f.read() return date
后端数据返回给前端页面(前后端交互)
静态网页:页面上的数据的直接写死的 基本不会在做修改(万年不变)
动态网页:数据是实时获取的
1.后端获取当前时间展示到html页面上
2.数据是从数据库中获取的,并展示到html页面上
# 通过replace将html页面中的指定字符替换成后端获取的格式化时间,再返回给html页面 import datetime def get_date(env): # 获取格式化当前时间 current_time = datetime.datetime.now().strftime('%Y-%m-%d %X') with open(r'templates/02 get_date.html', 'r', encoding='utf8') as f: data = f.read() # 获取到html页面的内容 # 通过replace将获取到的html内容中的字符串替换成后端我们获取到的格式化时间,再返回给html data = data.replace('get_date', current_time) return data
模板语法之Jinja2模块
注意:模板语法是在后端起作用的
// 前端页面获取到后端传递过来的数据 ''' 模版语法(十分贴近python语法),可以使用字典取值方式 {{user}} {{ user.get('name') }} {{user.age}} {{user['hobby']}} 模版语法也支持for循环 {% for user_dict in user_list %} <tr> <td>{{user_dict.id}}</td> <td>{{user_dict.name}}</td> <td>{{user_dict.age}}</td> <td>{{user_dict.hobby}}</td> </tr> {% endfor %} '''
后端代码
# 将一个字典传递给html页面,并且能够再html上便捷的操作字典数据(Jinja2) from jinja2 import Template def get_dict(env): current_dict = {'name':'king','age':18,'hobby':'read'} with open(r'templates/mydict.html', 'r', encoding='utf-8') as f: data = f.read() tmp = Template(data) # 给mydict.html传递了一个值,页面上通过user就可以拿到current_dict res = tmp.render(user=current_dict) return res
前后端以及数据库结合
# views.py(视图函数) 数据库连接,并获取数据库中对应表的数据 import pymysql def get_data(env): conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='asd123', db='day59', charset='utf8', autocommit=True # 自动提交 ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select * from userinfo' affect_rows = cursor.execute(sql) data_list = cursor.fetchall() # 将数据库中取出的数据字典存成列表 [{},{},{}] with open(r'templates/mydata.html', 'r', encoding='utf-8') as f: data = f.read() temp = Template(data) res = temp.render(user_list=data_list) return res # html页面 '''
模板语法使用 <tbody> {% for info in user_list %} <tr> <td>{{info.id}}</td> <td>{{info.name}}</td> <td>{{info.age}}</td> <td>{{info.hobby}}</td> </tr> {% endfor %} </tbody> '''
python三大主流web框架
Django:
特点:大而全 自带功能特别特别多 类似航空母舰
缺点:过于笨重
flask:
特点:小而精 自带功能特别特别少 类似游骑兵
第三方的模块特别特别的多,如果将flask第三方模块加起来完全可以盖过Django,并且也越来越像Django
缺点:比较依赖第三方的开发
tornado:
特点:异步非阻塞 支持高并发(强大之处甚至可以开发游戏服务器)
A:socket部分
B:路由与视图函数对应关系(路由匹配)
C:模版语法
django
A用的是别人的 wsgiref模块
B用的是自己的
C用的是自己的(没有jinja2好用 但是也很方便)
flask
A用的是别人的 werkzeug(内部还是wsgiref模块)
B自己写的
C用的别人的(jinja2)
tornado
A,B,C都是自己写的
Django框架
创建Django项目的注意事项
如何让你的计算机能够正常的启动django项目 1.计算机的名称不能有中文 2.一个pycharm窗口只开一个项目 3.项目里面所有的文件也尽量不要出现中文 4.python解释器尽量使用3.4~3.6之间的版本 ''' (如果你的项目报错 你点击最后一个报错信息去源码中把逗号删掉) ''' # django版本问题 1.X 2.X 3.X(直接忽略) 1.X和2.X本身差距也不大 我们讲解主要以1.X为例 会讲解2.X区别 公司之前用的1.8 慢慢过渡到了1.11版本 有一些项目用的2.0 # django安装 pip3 install django==1.11.11 如果已经安装了其他版本 无需自己卸载 直接重新装 会自动卸载安装新的 如果报错 看看是不是timeout 如果是 那么只是网速波动,重新安装即可 验证是否安装成功的方式 终端输入django-admin看看有没有反应
Django基本操作
# 命令行操作 # 1.创建django项目 """ 你可以先切换到对应的磁盘 然后再创建 """ django-admin startproject mysite(项目名) mysite项目文件夹 manage.py mysite文件夹 __init__.py settings.py urls.py wsgi.py # 2.启动django项目 """ 一定要先切换到项目目录下 cd d:mysite """ python3 manage.py runserver # http://127.0.0.1:8000/ # 3.创建应用 """ Next, start your first app by running python manage.py startapp [app_label]. """ python manage.py startapp app01 应用名应该做到见名知意 user order web ... # pycharm操作 # 1 new project 选择左侧第二个django即可 # 2 启动 1.还是用命令行启动 2.点击绿色小箭头即可 # 3 创建应用 1.pycharm提供的终端直接输入完整命令 2.pycharm tools run manage.py task提示(前期不推荐使用) # 4 修改端口号以及创建server edit configurations...
应用
# 一个app就是一个独立的功能 """ django是一款专门用来开发app的web框架 django框架就类似于是一所大学(空壳子) app就类似于大学里面各个学院(具体功能的app) 比如开发淘宝 订单相关 用户相关 投诉相关 创建不同的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', # 简写 ] # 创建出来的的应用第一步先去配置文件中注册 ps:你在用pycharm创建项目的时候 pycharm可以帮你创建一个app并且自动注册 ***********************************************************************
项目文件介绍
-mysite项目文件夹 --mysite文件夹 --settings.py 配置文件 --urls.py 路由与视图函数对应关系(路由层) --wsgi.py wsgiref模块(不考虑) --manage.py django的入口文件 --db.sqlite3 django自带的sqlite3数据库(小型数据库 功能不是很多还有bug) --app01文件夹 --admin.py django后台管理 --apps.py 注册使用 --migrations文件夹 数据库迁移记录 --models.py 数据库相关的 模型类(orm) --tests.py 测试文件 --views.py 视图函数(视图层)
命令行与pycharm创建的区别
# 1 命令行创建不会自动有templatew文件夹 需要你自己手动创建而pycharm会自动帮你创建并且还会自动在配置文件中配置对应的路径 # pycharm创建 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] ]} # 命令行创建 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], ]} """ 也就意味着你在用命令创建django项目的时候不单单需要创建templates文件夹还需要去配置文件中配置路径 'DIRS': [os.path.join(BASE_DIR, 'templates')] """
Django必会知识
""" HttpResponse 返回字符串类型的数据 return HttpResponse('这里是HttpResponse') render 返回html文件的 return render(request,'index.html') redirect 重定向 return redirect('https://www.mzitu.com/') return redirect('/home/') """
# django必会命令行 ''' 1、创建django项目: django-admin startproject mysite (ps:需要自己手动创建并配置templates) 2、启动django项目(切换到项目路径下),默认端口8000: python3 manage.py runserver # 网页打开127.0.0.1:8000 3、在项目中创建应用: python3 manage.py startapp app01 '''
from django.shortcuts import HttpResponse,render,redirect return HttpResponse('字符串') # 返回字符串 return render(request,'login.html') # 返回页面 def ab_render(request): # 视图函数必须要接受一个形参request user_dict = {'username':'jason','age':18} # 第一种传值方式:更加的精确 节省资源 # return render(request,'01 ab_render.html',{'data':user_dict,'date':123}) # 第二种传值方式:当传的数据很多时 """locals会将所在的名称空间中所有的名字全部传递给html页面""" return render(request,'01 ab_render.html',locals()) return redirect(url) # 重定向跳转到指定url