全部的Web应用本质就是一个socket服务端,用户使用的浏览器就是socket客户端html
软件开发架构:C/S架构和B/S架构,B/S架构本质也是C/S前端
一、纯手撸简易版web框架,实现根据用户输入的后缀不一样内容返回不一样的结果python
import socket server = socket.socket() server.bind(('127.0.0.1', 9876)) server.listen(5) while True: conn, addr = server.accept() data = conn.recv(1024) # Http协议的响应信息,HTTP/1.1表示当前协议为Http。1.1是协议的版本。200表示成功, OK表示好的 conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # print(data) data = data.decode('utf8') # 返回的是一串字符串,第二个字符串就是用户输入的后缀 # 获取用户输入的后缀内容 target_url = data.split('\r\n')[0].split(' ')[1] # 判断用户输入的内容返回不一样的内容 if target_url == 'index': conn.send(b'index') elif target_url == 'login': conn.send(b'login') else: conn.send(b'404 error') conn.close()
因为socket代码是咱们本身写的,HTTP数据也是咱们本身处理的太过麻烦,因此有了wsgiref模块mysql
二、wsgiref模块web
wsgiref模块能够帮咱们封装咱们写的web框架中的socket server部分sql
把路由关系与函数对应关系全写在一个py文件太过冗余,因此根据功能不一样拆分红不一样的文件:数据库
urls.py:路由与视图函数的对应关系django
views.py:里面就是存放一堆视图函数(视图函数能够是函数也能够是类)flask
templates文件夹(模板文件夹):里面放一堆HTML文件后端
用户在浏览器窗口输入url之因此能获取相应的资源是由于后端早已经开设相应的资源接口
from wsgiref.simple_server import make_server from urls import urls from views import * def run(env, response): ''' :param env: 请求相关的全部数据,接收的是大字典,里面的PATH_INFO参数就是用户输入的url后缀 :param response: 响应相关的全部数据 :return: 返回浏览器接收的内容 ''' response('200 OK', []) target_url = env.get('PATH_INFO') # 此处应该根据用户输入进行逻辑判断,为减小代码用for循环实现 # 先定义一个变量存储可能匹配的函数名 func = None for url in urls: # 判断用户输入的是否与urls一致 if target_url == url[0]: func = url[1] # 一旦有响应就马上结束,调转到响应url break # 判断是否有匹配上的 if func: # 加括号调用 res = func(env) else: res = error(env) return [res.encode('utf-8')] if __name__ == '__main__': # 监听'127.0.0.1:9876'一旦有访问就调用run执行 server = make_server('127.0.0.1', 9876, run) # 启动服务端 server.serve_forever()
基于wsgiref模块已经文件拆分的特色,在后端开设相应的资源接口1. 先在urls文件中写url与函数对应的关系。2. 再去views文件中写对应的函数
from views import * urls = [ ('/index', index), ('/login', login), ('/get_time', get_time), ]
def index(env): return 'index' def login(env): return 'login' def error(env): return '404 error'
# 须要返回一个HTML页面能实时获取时间的 import time def get_time(env): current_time = time.strftime('%Y-%m-%d %X') with open(r'E:\Python\templates\get_time.html','r',encoding='utf-8') as f: data = f.read() # 将HTML中的文本xxx替换成当前时间 data = data.replace('xxx',current_time) return data
动静态网页:静态网页:数据是写死的,不变的
动态网页:数据是动态获取的,好比获取当前时间,从数据库中获取数据
三、jinja2模块
提供了一个能够在HTML页面上书写相似于python后端的代码,来操做数据(模板语法)
下载:pip3 install jinja2
flask框架模板语法使用的就是jinja2模块,全部下载了flask框架就自动下载了jinja2模块
jinja2模板语法很是贴近python语法,可是并非全部的框架使用的都是jinja2模板语法
模板语法:在HTML中使用相似于python语法,本质在后端实现的,前端根本不识别
from jinja2 import Template def get_info(env): user_dic = {'username': 'shen', 'password': 123, 'hobby': ['study','read']} with open(r'E:\Python\templates\get_info.html','r', encoding='utf8') as f: data = f.read() temp = Template(data) res = temp.render(xxx=user_dic) return res
/-{{}}双大括号表示变量相关-/
{{xxx}} <p>{{xxx.username}}</p> <p>{{xxx['password']}}</p> <p>{{xxx.get('hobby')}}</p> <p>{{xxx.get('hobby')[0]}}</p> <p>{{xxx.get('hobby').1}}</p>
/-{% %} 大括号内有%%表示逻辑相关-/ {%for user_dict in xxx %} <tr> <td>{{ user_dict.password }}</td> <td>{{ user_dict.username }}</td> <td>{{ user_dict.hobby }}</td> </tr> {% endfor %}
四、获取数据库中的数据展现到前端页面
一、路由与视图函数对应关系
二、视图函数
三、模板文件夹
四、模板语法(是在后端实现的,前端根本不识别)
import pymysql
def get_user(env):
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
database='dome',
charset='utf8',
user='root',
password='2694',
autocommit=True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
sql = 'select * from user_info'
cursor.execute(sql)
data = cursor.fetchall()
with open(r'E:\Python\templates\get_user.html','r',encoding='utf-8') as f:
res = f.read()
tmp = Template(res)
res = tmp.render(xxx=data)
return res
<body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <table class="table table-hover table-bordered"> <thead> <tr> <th>id</th> <th>username</th> <th>password</th> <th>hobby</th> </tr> </thead> <tbody> {%for user_dic in xxx %} <tr> <td>{{ user_dic.id }}</td> <td>{{ user_dic.username }}</td> <td>{{ user_dic.password }}</td> <td>{{ user_dic.hobby }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body>
优势:大而全,自身携带的组件和功能特别多
缺点:笨重,当功能很少时不须要使用不少其余的功能
socket部分用wsgiref,路由分发用本身写的,模板渲染本身写的
优势:小而精,自身携带的组件和功能特别少,可是第三方支持该框架的模块特别特别多,叠加起来甚至能够超过Django
缺点:受限于第三方模块
socket部分用werkzeug,路由分发本身写的,模板渲染用jinja2
异步非阻塞,自然支持高并发,甚至能够开发游戏服务器
socket,路由分发,模板渲染都本身写
计算机名称不能有中文
项目文件名也不能有中文
一个pycharm窗口就是单独的完整的项目
1.xx版本与2.xx版本
推荐使用1.11.09~1.11.13
若是已经安装不须要手动卸载,从新安装会自动先卸载以前的版本再安装
pip3 install django==1.11.11
命令行输入django-admin
注意:python3.7与1.11.11不兼容能够更改Django的配置文件中一个数据便可
一、命令行
一、建立Django项目 : django-admin startproject 项目名
例:建立一个mysite项目:django-admin startproject mysite
效果:会建立一个mysite的文件夹
二、启动Django项目(先切换到项目目录下)
python manage.py runserver host:port # host:port 能够不写 默认是本机的127.0.0.1:8000
三、建立具备独立功能的app , 一般app名要见名知意:python manage.py startapp app名
例:python manage.py startapp app01
app的概念:application应用
Django实际上是一个专一于开发的app的web框架,一个空的Django框架就相似一所大学,一个个的app就至关于一个个学院,每一个app就相似于不一样的功能模块,不一样的功能模块推荐使用不一样的app去开发,Django支持多app
注意:一、使用命令行建立的Django项目不会建立templates模板文件夹,只能手动建立
二、命令行建立的Django项目配置文件settings中没有填写路径须要手动添加到环境变量中,pycharm建立的就会自动添加
二、pycharm快捷建立
pycharm启动Django
pycharm快捷建立app,会自动在配置文件中注册
mysite/ ├── manage.py # 管理文件 ├── db.sqlite3 # django自带的一个小型用于本地测试的数据库(对日期格式的数据不是很敏感) └── mysite # 项目目录 ├── __init__.py ├── settings.py # 配置 ├── urls.py # 路由 --> URL和函数的对应关系 └── wsgi.py # runserver命令就使用wsgiref模块作简单的web server └── app01 # 建立的app ├──migrations文件夹 数据库改动记录 ——__init__.py ├── __init__.py ├── admin.py # Django后台管理 ├── apps.py # 注册app相关 ├── models.py # 模型类(ORM) ├── tests.py # 测试文件 └── views.py # 视图函数
(*********)注意建立app后必定要先去settings文件中注册
修改代码始终没有效果
一、在同一个端口起了多个服务一直运行的是最开始的那个服务
二、浏览器缓存问题
一、HttpResponse:返回字符串
def index(request):
# return HttpResponse('字符串') return HttpResponse('你好 美女')
二、render:模板渲染(将数据在后端按照模板语法放入HTML对应的位置)
返回html页面,而且能够给HTML页面传数据
def login(request):
# return render(request, 'templates文件夹下的html文件',{传给HTML页面的数据}) return render(request,'login.html',{'user_dict':{'username':'shen','password':123},'xxx':'hello world'})
三、redirect:重定向
能够重定向到本身写的url上能够简写url只写结尾
也能够重定向到指定的url
def home(request): # return redirect('https://www.mzitu.com') return redirect('/index')
Django页面能够改为中文的,在配置文件中更改为下面的就行
LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False