Django从入门到放弃
基于socket手写web框架
py文件
import socket def server_run(): soc = socket.socket() soc.bind(('127.0.0.1', 8008)) soc.listen(5) while True: conn, addr = soc.accept() recv_data = conn.recv(1024) print(recv_data) # 1 直接在send里写,发送给客户端 # conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>hello web</h1><img src="https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=5e3814acf9edab64607f4592965fc4a6/14ce36d3d539b600c0c465d0eb50352ac65cb74b.jpg"></img>') #2 打开一个html文件,发送给客户端 # with open('index.html','r',encoding='utf-8') as f: # data=f.read() # conn.send(('HTTP/1.1 200 OK\r\n\r\n%s'%data).encode('utf-8')) # 3 动态网页,字符串替换 import time now=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) print(now) with open('index.html','r',encoding='utf-8') as f: data=f.read() data=data.replace('@@@',now) conn.send(('HTTP/1.1 200 OK\r\n\r\n%s'%data).encode('utf-8')) conn.close() if __name__ == '__main__': server_run()
index文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>@@@</h2> <img src="https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=5e3814acf9edab64607f4592965fc4a6/14ce36d3d539b600c0c465d0eb50352ac65cb74b.jpg" alt=""> </body> </html>
基于wsgiref定义自己的web框架
wsgirefServer.py
from wsgiref.simple_server import make_server from url import urls from views import error def run(env,response): print(env) response("200 OK",[('Content-type','text/html')]) position=env['PATH_INFO'] func=None for url in urls: if position==url[0]: func=url[1] break if func: response=func(env) else: response=error(env) return [response.encode('utf-8')] # 错误开头 # 1 服务器正在给我处理 # 2 成功 # 3 重定向 # 4 客户端错误 # 5 服务器错误 if __name__ == '__main__': ser=make_server('127.0.0.1',8003,run) ser.serve_forever()
url.py
from views import * urls=[ ('/index',index), ('/time',time), ('/test',test) ]
views.py
def index(env): return 'index' def time(env): return 'time' def error(env): return '404' def test(env): return 'test'
升级版
views.py
import datetime from jinja2 import Template def index(env): with open('templates/index.html', 'r') as f: data = f.read() return data def time(env): ctime = datetime.datetime.now().strftime('%Y-%m-%d %X') with open('templates/time.html') as f: data = f.read() data = data.replace('@@time@@', ctime) return data def error(env): return '404' def test(env): with open('templates/test.html', 'r') as f: data = f.read() tem = Template(data) response = tem.render(user={'name': 'yb', 'age': 18}) return response
template文件夹下
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>index页面</h1> </body> </html>
test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{user.name}} {{user.age}} </body> </html>
time.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> @@time@@ </body> </html>
三大主流框架分析
python中的web框架
a :socket
b:路由跟视图函数匹配关系
c:模板渲染
django: a: 用了别人的wsgiref b:自己写的 c:自己写的
flask: a:用了别人的 b:自己写的 c:用了别人的:jinja2
tornado: a 自己写的 b:自己写的 c:自己写的
http协议分析
http协议:
-特点:
1 基于TCP/IP协议之上的应用层协议
2 基于请求-响应模式
HTTP协议规定,请求从客户端发出,最后服务器端响应该请求并 返回。换句话说,肯定是先从客户端开始建立通信的,服务器端在没有 接收到请求之前不会发送响应
3 无状态保存
HTTP是一种不保存状态,即无状态(stateless)协议。HTTP协议 自身不对请求和响应之间的通信状态进行保存。也就是说在HTTP这个 级别,协议对于发送过的请求或响应都不做持久化处理。
4 无连接
无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
-请求格式:
请求方式:get与post请求
- GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditBook?name=test1&id=123456,POST方法是把提交的数据放在HTTP包的请求体中。
- GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制。
- GET与POST请求在服务端获取请求数据方式不同。
''' GET请求 # 请求首行 GET / HTTP/1.1\r\n # get请求后面的参数 GET /?name=lqz&age=18 HTTP/1.1\r\n # 请求头 Host: 127.0.0.1:8008\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 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\n Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\n Accept-Language: zh-CN,zh;q=0.9\r\n Cookie: csrftoken=7xx6BxQDJ6KB0PM7qS8uTA892ACtooNbnnF4LDwlYk1Y7S7nTS81FBqwruizHsxF\r\n\r\n' # 请求体(get请求,请求体为空) ''' ''' POST请求 # 请求首行 POST /?name=lqz&age=18 HTTP/1.1\r\n # 请求头 Host: 127.0.0.1:8008\r\nConnection: keep-alive\r\nContent-Length: 21\r\nCache-Control: max-age=0\r\nOrigin: http://127.0.0.1:8008\r\nUpgrade-Insecure-Requests: 1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8008/?name=lqz&age=18\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=7xx6BxQDJ6KB0PM7qS8uTA892ACtooNbnnF4LDwlYk1Y7S7nTS81FBqwruizHsxF\r\n\r\n # 请求体 name=lqz&password=123' '''
get请求和post请求的是使用情境
get:获取数据,页面,携带数据是不重要的数据(数据量有大小限制)
post:往后台提交数据
响应协议
响应格式
响应状态码
响应状态码指的是当客户端向服务器发送请求时,返回的请求结果。借助状态码,用户可以知道服务器是正常处理了请求,还是出现了错误。状态码如200 OK,以3位数字和原因短语组成,数字的第一位数字表示响应的类别,后面两位无类别。响应类别有以下5种。
URL简介(统一资源定位符)
统一资源定位符是对可以从互联网得到的资源的位置和访问方法的一种简洁表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
协议格式
协议://IP:端口(80)/路径?name=sqs&age=18
?之前的是请求路径,?之后的是请求数据部分
补充
#拿到数据库链接 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', db='lqz', password='admin') #获得游标,并且查询结果数据是字典格式 cur=conn.cursor(pymysql.cursors.DictCursor) #执行sql cur.execute('select * from user') #获取全部查询结果 dic=cur.fetchall()
-安装:1 pip3 install django==1.11.9 2 pycharm 下安装,选择版本号 -使用: 命令创建项目:django-admin startproject 项目名字 创建app:python3 manage.py startapp app01 -文件目录介绍: -manage.py---项目入口,执行一些命令 -项目名 -settings:全局配置信息 -urls:总路由,请求地址跟视图函数的映射关系 -app名字 -migrations:数据库迁移的记录 -models.py 数据库表模型 -views 视图函数 -运行项目: pytyon3 manage.py runserver 127.0.0.1:8001
静态文件配置
强调:创建了app,要在配置文件中注册
模板路径配置:
1 templates文件夹(没有的话手动创建一下)
2 settings里注册一下
静态文件配置:
1 STATIC_URL = '/static/' 一般不要改
2 创建一个static文件夹 一般不要改
3 STATICFILES_DIRS=[
os.path.join(BASE_DIR, 'static'), 创建的文件夹路径(可以写多个)
]
完整版登录功能
1 login.html
***重点***1 action:提交到后台的地址三种写法:
1 http://127.0.0.1:8000/login
2 /login/ 推荐用
3 空
2 method post方式
3 <input type="submit" value="提交">或<button></button>
type不可以是button
<form action="http://127.0.0.1:8000/login" method="post">
<p>用户名:<input type="text" name="name" class="form-control"></p>
<p >密码:<input type="password" name="pwd" class="form-control"></p>
<input type="submit" value="提交">
</form>
2 视图层:
1 request.method ----前台提交过来请求的方式
2 request.POST(相当于字典)----post形式提交过来的数据,(http请求报文的请求体重)
3 request.POST.get('name') ----推荐用get取值(取出列表最后一个值)
4 request.POST.getlist('name')-----取出列表所有的值_
5 前台get方式提交的数据,从request.GET字典里取
3 链接数据库(防止注入,推荐以下写法)
cur.execute('select * from user where name=%s and password=%s ',[name,pwd])
新手三件套总结
1 render--返回页面
默认会去templates里找,注意路径
2 redirect--重定向
3 HttpResponse
本质:都是返回HttpResponse的对象
ORM简介
ORM即Object Relational Mapping,全称对象关系映射。
优点:
不用写sql,不会sql的人也可以写程序
开发效率高
缺点:
可能sql的效率低
如何使用:
如果连接mysql:在setting里配置:
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'admin',
'NAME': 'lqz',
}
在app下的__init__.py里写:
import pymysql
pymysql.install_as_MySQLdb()
django-orm:
1 不能创建数据库(需要手动创建数据库)
2 可以创建数据表
3 可以创建字段
数据库迁移命令
在命令行中
1 python3 manage.py makemigrations ----记录一下数据库的变化
2 python3 manage.py migrate ----将变化同步到数据库中
在Run manage.py Task中
tools--->Run manage.py Task
python3 manage.py makemigrations
只需要敲命令:makemigrations(记录数据库的修改记录)
python3 manage.py migrate
只需要敲命令:migrate(把数据同步到数据库)
2 orm能干和不能干的事
1 能创建数据表,新增,删除字段
2 不能创建数据库
3 orm增加字段:(注意数据库迁移命令2条)
注意:后来增加的字段,需要有默认值
phone=models.CharField(max_length=64,default='120')
4 删除字段
注释掉字段,执行数据库迁移命令
5 修改数据
直接修改字段,执行数据库迁移命令
6 user的增删改查
***重点****:
1 单表查询所有用户:models.User.objects.all()
得到的是 queryset对象(当成列表),列表里面,一个一个的对象[user1,user2]
2 render(request, 'userlist.html', {'user_list': ret})
3 模板里: {% for user in user_list %}
#要循环的内容
{{user.name}}
{% endfor%}
4 get请求携带参数:
http://127.0.0.1:8000/deleteuser/?id=1
后台取值:request.GET.get('id')
request.GET['id']
5 orm删除记录 models.User.objects.filter(id=id).delete()
返回值:影响的行数
6 前台post提交的数据取值:name=request.POST.get('name')
7 orm保存:
两种方式:
1 user=models.User.objects.create(name=name,password=pwd,address=addr)
2 user=models.User(name=name,password=pwd,address=addr)
user.save()
8 orm查询单条数据:user=models.User.objects.filter(id=id).first()
9 orm的修改 models.User.objects.filter(id=id).update(name=name,password=pwd,address=addr)
django请求生命周期
8 图书管理系统多表设计
图书表--->出版社表---->一对多
一对多的关系一旦确立,关联字段写在多的一方
图书表--->作者表------>多对多
多对多关系,需要创建第三张表
图书表
出版社表
作者