Django框架简介(1)
手写web框架
# coding:utf8
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
# data 中的信息
"""
请求首行,表明请求方式以及遵循的http协议版本
b'GET / HTTP/1.1\r\n
请求头
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36\r\n
Sec-Fetch-User: ?1\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=aOZSalMQkKGbzstfjcw3O9sDoegdywL8AD7PzhidAyx3tXShN7oQtxN1MMnS6GVX\r\n
\r\n(******)
请求体
'
"""
while True:
conn, addr = server.accept() # 阻塞态
data = conn.recv(1024)
# print(data)
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
data_str = data.decode('utf-8')
current_path = data_str.split('\r\n')[0].split(' ')[1]
print(current_path)
if current_path == '/index':
# conn.send(b'index')
with open(r'01 纯手撸的前端页面.html','rb') as f: # 基于网络传输,所以用'rb'
conn.send(f.read())
elif current_path == '/login':
conn.send(b'login')
else:
conn.send(b'404 error')
conn.close()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1>你好呀,大兄弟!</h1>
<img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2973069531,657782944&fm=26&gp=0.jpg" alt="图片不存在!">
</body>
</html>
基于wsgiref模块写web服务端框架
基于第三方模块写web:
views.py 里面的放的是函数 我们管这些函数叫视图函数 视图层
urls.py 里面放的是 路由(后缀)与视图函数的对应关系 路由层
templates文件夹 里面放的全是html文件
# 服务端web框架文件
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','liu'),])
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() # 启动服务端
<!--templates文件夹中的html文件-->
# xxx.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
<script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<h1>我是xxx页面</h1>
</body>
</html>
# get_time.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
<script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
sadadadasdsadsad
</body>
</html>
# get_user.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
<script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<p>{{ userDic }}</p>
<p>{{ userDic.username }}</p>
<p>{{ userDic['age'] }}</p>
<p>{{ userDic.get('hobby') }}</p>
<p>{{ userDic.get('hobby').0 }}</p>
<p>{{ userDic.get('hobby').1 }}</p>
<p>{{ userDic.get('hobby').2 }}</p>
</body>
</html>
# get_data.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h2 class="text-center">数据展示</h2>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>idd</th>
<th>name</th>
<th>sex</th>
<th>age</th>
<th>hire_date</th>
<th>post</th>
<th>post_comment</th>
<th>salary</th>
<th>office</th>
<th>depart_id</th>
</tr>
</thead>
<tbody>
{% for user_dic in user_list %}
<tr>
<td>{{ user_dic.idd }}</td>
<td>{{ user_dic.name }}</td>
<td>{{ user_dic.sex }}</td>
<td>{{ user_dic.age }}</td>
<td>{{ user_dic.hire_date}}</td>
<td>{{ user_dic.post }}</td>
<td>{{ user_dic.post_comment }}</td>
<td>{{ user_dic.salary }}</td>
<td>{{ user_dic.office }}</td>
<td>{{ user_dic.depart_id }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
# view.py 文件
def login(env):
return 'login'
def index(env):
return 'index'
def reg(env):
return 'reg'
def xxx(env):
# return 'xxx'
with open(r'G:\Python代码日常\day051 django\templates/xxl.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'G:\Python代码日常\day051 django\templates/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':'zhang','age':18,'hobby':['read','book','run']}
with open(r'G:\Python代码日常\day051 django\templates/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 = '123',
db = 'db3',
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'G:\Python代码日常\day051 django\templates/get_data.html','r',encoding='utf-8') as f:
data = f.read()
temp = Template(data)
res = temp.render(user_list = user_list)
return res
# urls.py
from views import *
urls = [
('/login',login),
('/index',index),
('/reg',reg),
('/xxx',xxx),
('/get_time',get_time),
('/get_userdict',get_userdict),
('/get_data',get_data),
]
动静态网页
静态网页
数据是写死的 万年不变(哪怕改变了 也是人为直接修改)
动态网页
数据是实时获取的
eg:
1 后端代码动态获取 当前时间
2 数据是从数据库查询出来的
题目1
访问页面 页面上展示当前访问的时间
题目2
访问页面 页面上展示后端用户字典 并且在前端页面上可以
利用一些简便的方式操作字典取值
jinja2模板语法
专门用来处理后端数据与html页面的交互
模板语法(极其贴近python后端语法)
让你能够在html页面上 也能够用后端python语法来操作后端传递过来的数据
<p>{{ userDic }}</p>
<p>{{ userDic.username }}</p>
<p>{{ userDic['age'] }}</p>
<p>{{ userDic.get('hobby') }}</p>
<p>{{ userDic.get('hobby').0 }}</p>
<p>{{ userDic.get('hobby').1 }}</p>
<p>{{ userDic.get('hobby').2 }}</p>
{% for user_dic in user_list %}
<tr>
<td>{{ user_dic.id }}</td>
<td>{{ user_dic.username }}</td>
<td>{{ user_dic.password }}</td>
</tr>
{% endfor %}
基于jinja2模板语法 实现后端给html页面传值
模板语法是在后端生效的 浏览器是无法识别模板语法
所有的数据渲染全都是在后端事先生成好的 然后将完整的html页面丢给浏览器
{{ user_dic }}
{%for i in user_list%}
{%endfor%}
变量相关 {{}}
逻辑相关 {%%}
{# #} 模板语法的注释,该语法注释之后,前端是看不到的,而原生的html的语法注释<!-- 电话费的-->前端可以看到,注意区别。
python三大主流框架
django 大而全 自带的组件和功能非常非常多 类似于航空母舰
不足之处:写小项目的时候 可能会比较笨重(大材小用)
flask 小而精 短小精悍 自带的组件和功能特别特别少 类似于游骑兵
基本全部依赖于第三方组件
不足之处:受限于第三方模块的影响比较大
如果将flask所有第三方模块加起来 能够直接盖过django
tornado 异步非阻塞 这个框架甚至可以用来开发游戏服务器
a:socket部分
b:路由匹配
c:模板语法
django:
a用的别人的wsgiref(django默认的)
b自己写的
c自己写的
flask:
a用的别人的werkzeug
b自己写的
c用的别人的jinja2
Tornado:
a,b,c都是自己写的
django框架介绍
注意事项
*1.计算机名称不能有中文
2.python解释器不要使用3.7版本 推荐使用版本3.4~3.6,对Django兼容性比较好
3.一个pycharm窗口 只能跑一个项目,项目名不要有中文*
django版本问题
django版本以1.11.11为主(1.11.9~1.11.13)
django下载方法
方式一:pycharm settings中安装
方式二:cmd安装
pip3 install django==1.11.11
如何检验django是否安装成功:
命令行敲 django-admin
django项目及app的创建
命令行创建项目
1.创建django项目
django-admin startproject 项目名(例如mysite)
2.启动django项目
切换到项目文件夹下
python3 manage.py runserver
python3 manage.py runserver 127.0.0.1:8080
3.停止项目
ctrl+c
4.创建应用(django支持多app开发)
python3 manage.py startapp app01
注意:
1.命令行创建不会自动创建templates文件夹
2.配置文件中不会自动帮你书写templates文件路径
pycharm创建项目
方法一:FILE>>>new project 选择第二个Django,命名项目名的时候名字不能为中文
创建app,在Application中添加应用的名,直接创建项目及应用;可以不添加,后期手动创建应用。
方法二:打开菜单栏Tools>>>run manage task功能栏创建项目及应用
创建好的app需要在django配置文件中注册方可生效
强调:
1.用Django一定要保证只有一个在运行状态
2.调试Django项目的时候,一定记得清除浏览器的缓存(如果页面调试没有达到代码改的效果)
浏览器页面右键:检查》network》 Settings》Preferences》Network》Disable cache(while DevTools is open) 打上勾;
3.如果想想使用Django默认的端口可以自己修改,方法如下图:
app的概念
django是一个以开发app为主要功能的web框架
app就是application应用的意思
一个django项目就是一所大学(空的架子 本身没有任何功能),而app就类似于大学里面的各个学院;
一个空的django本身没有任何作用 仅仅是为app提高前期的环境配置
你可以根据功能的不同 开发多个app
一个app对应一个具体的功能模块
用户相关的功能 用户相关的app
订单相关的功能 订单相关的app
商品相关的功能 商品相关的app
每一个app都有自己独立的功能
Django主要文件介绍
应用文件夹(app)
migrations 数据库迁移记录相关数据
adnin.py django后台管理相关
models.py 模型表相关
views.py 视图函数相关
项目名
settings.py 配置文件
urls.py 路由与视图函数的映射关系
templates文件夹 项目用到的所有的html文件
manage.py django入口文件
Django基础必会的三个函数
from django.shortcuts import HttpResponse, render, redirect
HttpResponse
内部传入一个字符串参数,返回给浏览器。
# views.py
def index(request):
# 业务逻辑代码
return HttpResponse("你好,世界!")
# urls.py
from firstapp import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index), # 添加对应的功能函数
]
# 启动服务端:Starting development server at http://127.0.0.1:9999/
# 在浏览器页面用 http://127.0.0.1:9999/index/连接服务端,将index函数内部字符串渲染到浏览器页面上。
render
除request参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数。
将数据填充进模板文件,最后把结果返回给浏览器。(类似于我们上面用到的jinja2)
# views.py
def reg(request):
user_dic = {'username':'zhang','password':123}
# 下面两种方法都可以
return render(request,'reg.html',local()) # 拿到reg函数内部所有的局部变量,在html文件内部可以根据模板语法选择你要渲染到前端页面上的变量。
# return render(request,'reg.html',{'user_dic':user_dic})
# urls.py
from firstapp import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^reg/', views.reg),
]
# templates 文件夹建立 reg.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<form action="" class="form-control">
<label for="">username:<input type="text"></label>
<label for="">password<input type="text"></label>
<input type="submit" class="提交">
{{ user_dic }}
<div>{{user_dic.username }}</div>
<div>{{ user_dic.password }}</div> # 只支持点的方式,不支持字典的取值方式
</body>
</form>
</body>
</html>
# 启动服务端:Starting development server at http://127.0.0.1:9999/# 在浏览器页面用 http://127.0.0.1:9999/reg/连接服务端,将reg函数内部reg.html 文件渲染到浏览器页面上。
redirect(重定向)
接受一个URL参数,表示跳转到指定的URL(当前页面跳转)。
1)可以写本网站的路径后缀;
2)也可以写全路径,即:任意一个网页地址。
# views.py
def login(request):
# return redirect('http://www.baidu.com') # 访问login后缀名,重定向到百度网址
return redirect('/reg') # 本网站的后缀名
# urls.py
from firstapp import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^reg/', views.reg),
url(r'^login/', views.login),
]
# 启动服务端:Starting development server at http://127.0.0.1:9999/# 在浏览器页面用 http://127.0.0.1:9999/login/连接服务端,按照login函数内部redirect指定的网址跳转,或者路径=后缀。
注意:Django能自动识别到你对代码的修改,所以无需重启服务端,但是有时候识别比较缓慢,最好重新手动启动,也可以多刷新几次浏览器页面