一、Django简介
Django简介
1、软件开发架构
"""
CS架构
BS架构
本质上来说,BS架构也是CS架构
"""
2、Web框架
-
Web框架本质:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。
-
HTTP协议
# HTTP协议是一种网络协议 # 网络协议 """ HTTP协议 数据传输是明文 HTTPS协议 数据传输是密文 websocket协议 数据传输是密文 """ # HTTP协议的特性 """ 1.基于请求响应 2.基于TCP/IP作用于应用层之上的协议 3.无状态 4.短/无链接 """ # 数据格式 """ 请求首行 请求头 \r\n 请求体 """ # 响应状态码 """ 1XX 2XX 200 3XX 4XX 403 404 5XX 500 """
3、手撸Web框架
# 你可以将web框架理解成服务端
import socket
server = socket.socket() # TCP 三次握手四次挥手 osi七层
server.bind(('127.0.0.1',8080)) # IP协议 以太网协议 arp协议...
server.listen(5) # 池 ...
"""
b'GET / HTTP/1.1\r\n
Host: 127.0.0.1:8082\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
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\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;q=0.9\r\n
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Sec-Fetch-Dest: document\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=KYJnVBLPpJxwt09TOmTXzpb5qkFJwHVxVGpi0NxEGIg4z5VUuazZ1O2RMwSisu14\r\n
\r\n'
"""
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\r\n\r\n')
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()
- 不足之处:
- 代码重复(服务端代码所有人都要重复写)
- 手动处理http格式的数据 并且只能拿到url后缀 其他数据获取繁琐(数据格式一样的处理代码大致也是一样的)
- 并发问题没处理
4、借助于wsgiref模块撸Web
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 路由与视图函数对应关系 views.py 视图函数(后端的业务逻辑) manage.py 启动代码 templats文件夹 用来存放HTML """
5、动静态页面
-
静态页面
- 页面上的数据是直接写死的,不会变化
-
动态页面
- 页面上的数据是实时获取的
-
具体示例
# 动态网页制作1 # 主要方法是获取后端页面代码(字符串),替换字符串中的某些数据为我们后端写的代码,比如下面的时间 import datetime def get_time(env): current_time = datetime.datetime.now().strftime('%Y-%m-%d %X') # 如何将后端获取到的数据"传递"给html文件? with open(r'templates/03 mytime.html','r',encoding='utf-8') as f: data = f.read() # data就是一堆字符串 data = data.replace('dwadasdsadsadasdas',current_time) # 在后端将html页面处理好之后再返回给前端 return data # 动态页面制作2 # 将一个字典传递给html文件 并且可以在文件上方便快捷的操作字典数据 from jinja2 import Template def get_dict(env): user_dic = {'username':'jason','age':18,'hobby':'read'} with open(r'templates/04 get_dict.html','r',encoding='utf-8') as f: data = f.read() tmp = Template(data) res = tmp.render(user=user_dic) # 给get_dict.html传递了一个值 页面上通过变量名user就能够拿到user_dict return res # 后端获取数据库中数据展示到前端页面 <body>
-
模板语法之jinja2模块
# 模版语言 # 可以简单的取值 {{ user }} {{ user.get('username')}} {{ user.age }} {{ user['hobby'] }} # 也可以for循环创建table {% for user_dict in user_list %} <tr> <td>{{ user_dict.id}}</td> <td>{{ user_dict.username}}</td> <td>{{ user_dict.password}}</td> <td>{{ user_dict.hobby}}</td> </tr> {% endfor%} </body>
6、三大主流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都是自己写的
"""
7、启动一个Django项目
①、启动前的注意事项
- 计算机问题
- 计算机名称不能有中文
- 一个pycharm窗口只能开一个项目
- 项目里面的所有文件尽量使用英文
- python解释器尽量使用3.4~3.6之间的版本,(如果用高级版本的python可能会报错,点击最后一个报错信息,删除最后一个逗号即可)
- Django版本问题
- 1.X、2.X用的比较多,由于3.X是最新发布的,优先不考虑
- 目前使用的是1.11.11
- Django安装
- 命令行输入:pip3 install django==1.11.11
- 在pycharm里的setting中安装,注意切换python解释器
- 检验安装是否成功:在命令行输入Django-admin
②、Django的基本操作(终端版)
-
创建Django项目
-
到指定的盘符下面cmd输入:django-admin startproject mysite
-
此时会创建一个mysite文件夹
# 文件夹详情 """ - mysite -- manage.py -- mysite文件夹 --- __init__.py --- setting.py --- urls.py --- wsgi.py """
-
-
情动Django项目
- cmd切换到mysite文件夹下,输入:python manage.py runserver
-
创建应用
- cmd到mysite文件架下面,输入:python manage.py startapp app01(app的名称应该见名知意)
③、Django基本操作(pycharm版)
- 创建项目:点击新建项目即可(注意python解释器)
- 启动:pycharm命令行或者命令行启动manage.py文件
- 创建app:pycharm命令行,或者点击tools,点击run manage.py task...提示创建
- 修改端口号:点击edit config
④、应用(APP)
-
Django是一款专门开发app的web框架,这里的app不是手机上的app,而是功能的意思。一个app代表一类功能,一个Django框架就是一群app的集合体。
-
注意:每次创建完app后都要到settings里面注册
# 找到项目下的settins.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', # 全写 'app01', # 简写 ]
⑤、主要文件介绍
# mysite(项目文件夹)
"""
- mysite(文件夹)
-- settings.py(配置文件)
-- urls.py(路由与视图层的对应关系)路由层
-- wsgi.py(wsgiref模块 不考虑)
- manage.py(启动文件)
- db.splite3(自带的小型数据库,功能不是很完善还有很多bug)
- app01(文件夹)
-- admin.py(Django后台管理)
-- apps.py(注册使用)
-- migrations.py(数据迁移记录)
-- models.py(数据库相关的模型类 ORM)
-- test.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
-
在views.py文件中使用,返回字符串类型的数据
return HttpResponse('字符串')
-
-
render
-
在views.py文件中使用,返回HTML文件
return render(request,'login.html')
-
reder的传值方式
def ab_render(request): user_info = {'username':'jason','age':18} # 第一种传值方式:传值更加精确,节省资源 return (request,'login.html',{'data':user_info}) # 第二种传值方式:当需要传的值比较多的时候 """locals会将所在的名称空间中所有的名字都传给HTML页面,包括request""" return (request,'login.html',locals())
-
-
redirect
- 重定向
- 指定页面:return redirect(‘https://www.baidu.com’)
- 拼接当前页面:return redirect(‘home’)
8、静态文件配置
①、前戏
-
引子:在写项目时我们默认把HTML文件放在template文件夹下,而网站使用的静态文件放在static文件夹下
-
静态文件:前端已经写好地直接调用的文件夹
- 前端使用的框架
- JS脚本
- CSS样式
- 图片
-
static文件夹详情
""" - static -- js -- css -- img -- others(框架) """
②、如何配置
-
在setting中配置
# static类似于访问静态文件的令牌 STATIC_URL = '/static/' # 静态文件的文件路径,可以有多个 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), os.path.join(BASE_DIR,'static1'), os.path.join(BASE_DIR,'static2'), ]
-
静态文件动态解析(在前端页面书写)
{% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
-
补充
-
在浏览器中输入url能够看到对应的资源,是因为后端提前开设了该url的资源接口。如果访问不到资源,说明后端没有开设该url的资源接口
-
form表单的action参数
- 不写:默认朝当前所在的url提交数据
- 全写:指名道姓朝哪个url提交数据
- 只写后缀:/login/,朝后端login这个视图函数提交数据
-
前期使用Django提交post请求时,需要在setting中注释一行代码
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', ]
-
9、request对象初识
-
对象初识
- reques.method:返回请求方式,并且是全大写的字符串
- request.POST:获取用户post请求提交的数据,不包含文件
- request.POST.get():只获取列表最后一个元素
- request.POST.getlist():直接获取列表中的全部元素
- request.GET:获取用户提交的get请求数据
- request.GET.get():只获取列表最后一个元素
- request.GET.getlist():直接获取列表中的全部元素
-
具体示例
request.method # 返回请求方式 并且是全大写的字符串形式 <class 'str'> request.POST # 获取用户post请求提交的普通数据不包含文件 request.POST.get() # 只获取列表最后一个元素 request.POST.getlist() # 直接将列表取出 request.GET # 获取用户提交的get请求数据 request.GET.get() # 只获取列表最后一个元素 request.GET.getlist() # 直接将列表取出 """ get请求携带的数据是有大小限制的 大概好像只有4KB左右 而post请求则没有限制 """ def login(request): # 返回一个登陆界面 """ get请求和post请求应该有不同的处理机制 :param request: 请求相关的数据对象 里面有很多简易的方法 :return: """ # print(type(request.method)) # 返回请求方式 并且是全大写的字符串形式 <class 'str'> # if request.method == 'GET': # print('来了 老弟') # return render(request,'login.html') # elif request.method == 'POST': # return HttpResponse("收到了 宝贝") if request.method == 'POST': return HttpResponse("收到了 宝贝") return render(request, 'login.html')
10、pycharm连接数据库(MySQL)
- pycharm中数据库位置
- 右侧上方database
- 左下方database
- settings中的plugins插件搜索database安装
- 具体使用:和navigate里的一样操作
11、Django连接数据库
-
前戏:Django中的数据库默认是用sqlite3
-
具体配置
-
在settings.py中配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day60', 'USER':'root', 'PASSWORD':'admin123', 'HOST':'127.0.0.1', 'PORT':3306, 'CHARSET':'utf8' } }
-
代码声明
# 在项目名的init.py或者任意应用名下的init.py文件中书写以下代码 import pymysql pymysql.install_as_MySQLdb()
-