Django的学习需要掌握的一些基础和初步搭建自己的框架
一.Django的学习需要掌握的一些基础
第一个需要注意的点:客户端发送过来的数据结构组成:
第二个需要注意的点:动态网页和静态网页
静态网页:用户发送请求,服务端找到对应的静态文件返回给浏览器,静态网页时不变的,用户恮什么就返回什么,不能和用户交互。
动态网页:动态网页和静态网页的区别就是动态网页能和用户进行交互,根据用户的需求随时调换不同的静态页面返回给浏览器。
疑问:1.wsgiref怎么把套接字封装的?
WSGI_APPLICATION = 'untitled7.wsgi.application'
wsgiref是把socket封装起来,不用再去手动生成。
2.make_server()和serve_forever()
3.ico图标的问题
请求头最后的\r\n是标识着请求头的结束,请求体即将开始。我的理解是两个\r\n是他们中间空一格,两次换行,开启请求体内容输出,更好的区分头和体。
1 import socket 2 # 客户端和服务端的传输:套接字通信 3 soc=socket.socket() 4 # 绑定的是元组 5 soc.bind(('127.0.0.1',8001)) 6 soc.listen(5) 7 8 # 通信循环 9 while True: 10 print('监听8001端口') 11 # addr是客户端的IP+Port 12 #conn是建双向连接对象,soc是套接字对象 13 conn,addr=soc.accept() 14 # 接收到的客户端数据 15 data=conn.recv(1024) 16 # 转换成str类型 17 # str()函数里面第一个参数是需要转的数据,第二个是指定的字符编码类型。下面是将二进制转成字符串 18 data=str(data,encoding='utf-8') 19 print(data) 20 # 我们打印获得的字符串,发现客户端发送过来的数据之间是按照'\r\n'有规律的分开的,待会再说分开有何意义。 21 # 我们可以将这些数据按照发现的规律用split分割开来,返回一个有一定规律的列表。 22 # 取出列表第一个,再把他们通过空格分开来,返回一个请求首行组成的列表。 23 resquest_list=data.split('\r\n') 24 first_list=resquest_list[0].split(' ') 25 conn.send(b'HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n\r\n') 26 if first_list[1]=='/index': # 如果请求首行第二个元素(也就是请求地址)等于'/index' 27 # conn.send('<h1>index</h1><img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=775f519ac08065386fe7ac41f6b4ca21/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg">'.encode('utf-8')) 28 with open('index.html','rb')as f: 29 data=f.read() 30 conn.send(data) # 将服务端的数据发送给浏览器,浏览器对数据进行渲染=====》静态网页 数据写死了 31 elif first_list[1]=='/two': 32 with open('two.html','r',encoding='utf-8')as f: 33 data=f.read() 34 import datetime 35 now=datetime.datetime.now().strftime('%Y-%m-%d %X') 36 data=data.replace('@@time@@',now) # ======》动态网页 网页数据没有固定死 37 conn.send(data.encode('utf-8')) 38 else: 39 conn.send(b'404') 40 41 42 # print(data) 43 # 44 # conn.send(b'HTTP/1.1 200 OK \r\n\r\nhello web') 45 conn.close() 46 47 ''' 48 # 请求首行:请求类型 请求地址 请求协议 49 GET /index HTTP/1.1\r\n 50 # 请求头 51 Host: 127.0.0.1:8001\r\n 52 Connection: keep-alive\r\n 53 Cache-Control: max-age=0\r\n 54 Upgrade-Insecure-Requests: 1\r\n 55 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36\r\n 56 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n 57 Accept-Encoding: gzip, deflate, br\r\n 58 Accept-Language: zh-CN,zh;q=0.9\r\n\r\n' 59 60 # 请求体 61 。。。。 62 63 '''
请求---》处理---》调用函数---》打开模板和数据库---》返回数据给浏览器---》浏览器解析渲染
下面分三个文件来说明:
用wsgiref搭建简单的服务端
1 from wsgiref.simple_server import make_server 2 import my_urls 3 from views import * 4 5 6 def my_server(environ, start_response): 7 # print(environ) environ返回的是一个字典,path_info是字典里的key,对应的值是请求地址 8 print(environ['PATH_INFO']) # 'PATH_INFO': '/index' PATH_INFO就是请求地址 9 start_response('200 OK', [('Content-Type', 'text/html')]) # 服务器响应状态码:200 文本类型:text 10 func=None 11 for url in my_urls.urls: 12 if url[0]==environ['PATH_INFO']: 13 func=url[1] # 这里的func是函数地址 14 break # 结束循环 15 if func: 16 # 固定写法,如果不写environ也可以,但是要求函数必须也不能有形参 17 # 不写的话报错:missing 1 required positional argument: 'response' 18 response=func(environ) 19 else: 20 response= error(environ) 21 22 return [response,] # 这里是固定返回一个列表,用别人的就要按照别人的要求来 23 24 25 if __name__ == '__main__': 26 27 my=make_server('127.0.0.1',8002,my_server) 28 my.serve_forever()
视图函数
用到jinja2模块中的template
1 # 视图函数 2 import pymysql 3 from jinja2 import Template 4 def index(response): 5 with open('templates/index.html','r',encoding='utf-8') as f: 6 data=f.read() 7 8 return data.encode('utf-8') 9 10 def time(response): 11 import datetime 12 now=datetime.datetime.now().strftime('%Y-%m-%d %X') 13 with open('templates/two.html','r',encoding='utf-8') as f: 14 data=f.read() 15 data=data.replace('@@time@@',now) 16 return data.encode('utf-8') 17 18 19 def user_list(response): 20 # 连接数据库拿数据 21 # 拿到一个数据库连接 22 conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',database='test',password='egon123') 23 # 拿到一个游标对象 24 cursor=conn.cursor(cursor=pymysql.cursors.DictCursor) 25 # 执行sql 26 cursor.execute('select * from user') 27 # 把数据拿出来 28 user_list=cursor.fetchall() 29 print(user_list) 30 with open('templates/user_list.html','r',encoding='utf-8')as f: 31 data=f.read() 32 # 生成一个模板对象,需要传字符串 33 template=Template(data) 34 # 相当于在执行data.replace(),返回替换完成的字符串 35 data=template.render(user_list=user_list) 36 37 38 39 return data.encode('utf-8') 40 def error(request): 41 return '404'.encode('utf-8') 42 43 44 def favicon(request): 45 with open('favicon.ico','rb') as f: 46 data=f.read() 47 return data
路由:路由的作用就是建立请求地址与索引之间的关系--》服务端解析出请求地址,然后调用对应的函数
import views # 路由 urls=[ ('/index',views.index), ('/time',views.time), ('/user_list',views.user_list), ('/favicon.ico',views.favicon), ]
下面是三个模板中的html文件
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 <img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=775f519ac08065386fe7ac41f6b4ca21/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg">' 10 11 </body> 12 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 @@time@@ 9 </body> 10 </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户列表</title> </head> <body> <table border="1"> <thead> <tr> <th>id</th> <th>用户名</th> <th>密码</th> </tr> </thead> <tbody> {% for user in user_list%} <tr> <td>{{user.id}}</td> <td>{{user.name}}</td> <td>{{user.password}}</td> </tr> {%endfor%} </tbody> </table> </body> </html>
放一张简单的django工作图
附上文字说明:
图片解析:浏览器向服务器发送url地址:ip+port+请求地址 ,服务端对请求地址进行解析,获得客户端发来的请求地址,然后
通过路由循环服务端的请求地址,有匹配成功的就调用服务端的函数,函数从模板templates中调用html文件,如果需要从数据库
调用数据则需要导入pymysql,获得的数据列表最后需要通过模板对象进行渲染,浏览器客户端解析html,并对模板按照要求进行
相应的渲染。
很形象的一个流程图
二.初步搭建自己的框架
1.安装django的三种方式
方式二
方式三
2.如何创建自己的django项目?
1.首先切换到一个放项目的目录下
2.在命令行输入:
django-admin startproject django项目名
3.切换到项目目录,启动manage文件 python3 manage.py runserver
可以通过端口+ip查看自己的django项目
3.如何在pycharm里启动Django?
3.1 直接在新窗口打开django所在位置
terminal运行python3 manage.py runserver
越是困难的事越要立即去做,这样收益才会最大!!!