Django框架
一、学习准备
1、下载安装Django(建议安装1.x版本)
方法:终端cmd输入命令:pip install django==1.11.12 然后回车即可
校验是否安装成功:django-admin
OK这里暂时先到这里,接下来要模拟Django的原理,后面会重点介绍Django的语法以及创建
二、纯手撸web框架
1.纯手撸web框架
软件开发架构
c/s架构
b/s架构
本质bs也是cs
web后端
需求:
1.根据用户输入不同的后缀返回不同的内容
从符合http协议格式的数据中获取用户输入的后缀
不足之处:
1.socket代码是我们自己写的
2.http数据也是我们自己处理的
import socket server = socket.socket() server.bind( ('127.0.0.1', 8080) ) server.listen(5) """ 请求首行 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/75.0.3770.80 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\r\n Accept-Encoding: gzip, deflate, br\r\n Accept-Language: zh-CN,zh;q=0.9\r\n \r\n 请求体 ' """ while True: conn, addr = server.accept() data = conn.recv(1024) conn.send(b'HTTP/1.1 200 OK\r\n\r\n') data = data.decode('utf--8') # 一串字符串 target_url = data.split('\r\n')[0].split(' ')[1] #判断url返回响应的内容 if target_url == '/index': with open(r'D:\python的pycharm\正式课\day49\templates\01 demo.html', 'rb') as f: conn.send(f.read()) elif target_url == '/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 href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <h1>我是一个正儿八经的html页面</h1> </body> </html>
效果演示:
三、基于wsgiref模块
基于wsgiref模块撸:
根据功能的不同拆分成不同的文件
用户在浏览器窗口输入url之所以能够获取到相应的资源
是因为后端早已经开设了相应的资源接口
基于wsgiref模块以及文件拆分的特点
只要你想要开设新的资源
1.先在urls文件中写url与函数的对应关系
2.再去views文件中写对应的函数
urls.py:路由与视图函数的对应关系
views.py:里面就是放的一堆视图函数(视图函数可以是函数也可以是类)
templates文件夹:里面放的就是一堆html文件(模板文件夹)
from wsgiref.simple_server import make_server from views import * from urls import urls def run(env, response): ''' :param env: 请求相关的所有数据 :param response: 响应相关的所有数据 :return: 浏览器能够接受的内容 ''' response('200 OK', []) # print(env) # 大字典 里面的PATH_INFO参数就是用户输入的后缀 target_url = env.get('PATH_INFO') # 先定义一个变量 用来存储可能匹配到的函数名 func = None # 1、for循环获取一个个的url与函数对应关系的元祖 for url in urls: # url = (),(),() # 2、判断当前用户访问的url与元祖第一个元素是否一致 if target_url == url[0]: # 3、如果相等 说明有对应的后端逻辑代码 将匹配到的函数名赋值给func func = url[1] # 4、一旦用户匹配上了响应的url 应该立刻结束当前的for循环 因为没有意义 break # 针对func是否有值 还需要判断 if func: # 匹配上了 加括号直接调用 res = func(env) #这里加上env是为了防止后期用户还需要获取访问者的ip以及端口,所以为了后期做准备 else: # 匹配404 逻辑代码 res = error(env) return [res.encode('utf-8')] # 返回函数的返回值 这里在最后加encode是为了方便 if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) # 监听127.0.0.1:8080 一旦有客户端来访问 会立刻将make_server第三个函数加括号调用执行 server.serve_forever() # 启动服务端
from views import * '''url对应的是路由以及视图的对应关系''' urls = [ ('/index', index), ('/login', login), ('/xxx', xxx), ('/get_time', get_time), ('/get_user', get_user), ('/get_info', get_info) ]
'''views做逻辑判断''' def index(env): return 'index' def login(env): return 'login' def error(env): return '404 error' def xxx(env): return 'xxx' import time def get_time(env): # 该函数需要返回一个html页面 current_time = time.strftime('%Y-%m-%d %X') # 字符串 # 文件操作 读取HTML文件 with open(r'D:\python的pycharm\正式课\day49\templates\02 get_time.html','r', encoding='utf-8') as f: # 这里是要用r模式,就让他是字符串的类型,后面有用 data = f.read() # 读取html文件内容 字符串 data = data.replace('gfdgsfdgfdsgsfdgsfdgsfdgsdg', current_time) # 这里利用了字符串的替换 return data from jinja2 import Template # jinja2 模块 def get_user(env): user_dict = {'usename': 'yafeng', 'password': 123, 'hobby': ['study', 'read', 'running']} with open(r'D:\python的pycharm\正式课\day49\templates\03 get_user.html', 'r', encoding='utf-8') as f: data = f.read() temp = Template(data) res = temp.render(xxx=user_dict) # 将user_dict 传递给HTML页面 在页面上通过变量名xxx就可以获取到user_dict return res import pymysql def get_info(env): conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123456', database = 'day49', charset = 'utf8', autocommit = True ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select * from userinfo" cursor.execute(sql) data = cursor.fetchall() # [{},{},{}] #将列表套字典的结构数据 直接传递给HTML页面 with open(r'D:\python的pycharm\正式课\day49\templates\04 get_info.html', 'r', encoding='utf-8') as f: res = f.read() # 利用jinja2模块 tmp = Template(res) # 利用对象的render方法 将数据直接传给HTML页面 res = tmp.render(xxx=data) return res
<!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 href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> gfdgsfdgfdsgsfdgsfdgsfdgsdg </body> </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 href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> {{ 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> </body> </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 href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <h2 class="text-center">数据展示</h2> <div class="col-md-8 col-md-offset-2"> <table class="table-hover table table-striped"> <thead> <tr> <th>id</th> <th>username</th> <th>hobby</th> </tr> </thead> <tbody> <!-- xxx = [{},{},{},{}]--> {%for user_dict in xxx %} <tr> <td>{{ user_dict.id }}</td> <td>{{ user_dict.name }}</td> <td>{{ user_dict.hobby }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html>
效果演示:
四、动静态页面展示
动静态网页
静态网页
数据是写死的 万年不变
动态网页
数据是动态获取的
eg:
1.获取当前时间
2.从数据库中获取数据
需求:
1.你给我写一个对应关系 一旦访问立刻展示当前访问的时间
2.后端有一个用户字典 你需要将该字典传递给html页面 并且在该页面上还可以将传递过来的数据当成字典数据进行获取值的操作
jinja2模块
提供了一个可以在html页面上书写类似于python后端的代码 来操作数据(模板语法)
pip3 install jinja2
flask框架模板语法使用的就是jinja2模块,所以你只要下了flask框架 就会自动下载jinja2
模板语法(jinja2模板语法非常贴近python语法 但是并不是所有的框架使用的都是jinja模板语法)
{{ 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.id }}</td>
<td>{{ user_dict.name }}</td>
<td>{{ user_dict.hobby }}</td>
</tr>
{% endfor %}
获取数据库中数据 展示到前端页面
1.路由与视图函数对应关系
2.视图函数
3.模板文件夹
4.模板语法(是在后端实现的 前端根本不识别)
简易版本的web框架请求流程图:
五、python的web框架介绍
python三大主流web框架
django
大而全 自身携带的组件和功能特别特别多 就类似于航空母舰
不足之处:笨重
当你的功能不多 不需要使用很多其他功能
flask(源码600多行 请求上下文 应用上下文)
小而精 自身携带的组件和功能特别特别少 就类似于游骑兵
虽然自身功能比较少 但是第三方支持该框架的模块特别特别多
如果你将flask第三方模块全部叠加起来 甚至可以超过django
不足之处:受限于第三方模块
tornado
异步非阻塞
天然支持高并发 甚至可以用它来开发游戏服务器
六、Django框架
django框架
1.注意事项
1.计算机名称不能有中文
2.项目文件名也不要用中文
3.一个pycharm窗口就是一个单独的完整的项目
2.版本问题
1.X
2.X
推荐你使用1.X版本里面的
1.11.09~1.11.13
如果你已经按照过不需要手动卸载 重新安会自动先卸载之前的版本再安装
3.安装
pip install django==1.11.11
4.测试是否安装成功
命令行输入django-admin
如何创建django项目
1.命令行
1.创建django项目
django-admin startproject mysite(项目名)
效果:创建一个mysite的文件夹
mysite
-mysite
--__init__.py
--settings.py
--urls.py
--wsgi.py
-manage.py
2.启动django项目(先切换到项目目录下)
python manage.py runserver # django默认的端口号是8000
3.创建具有独立功能的app 通常情况下应该做到建明制衣
python manage.py startapp app01
app01
--migrations文件夹
--__init__.py
--admin.py
--apps.py
--models.py
--tests.py
--views.py
- 解决python3.7和Django1.x版本不兼容的问题
找到你的python下的这个文件夹(根据报错目录)
大功告成
注意(*******):
"""
1.使用命令行创建的django项目是不会自动创建templates摸版本文件夹 你只能自己手动创建
2.命令行创建的django项目不但没有templates文件夹配置文件中也没有填写路径
而pycharm创建的会自动添加
"""
2.pycharm快捷创建
七、APP概念
application 应用
django其实是一个专注于开发app的web框架
一个空的django项目就类似于是一所大学
app就类似于大学里面的各个学院
每个app其实就类似于不同的功能模块
购物网站
用户相关 user
用户相关的app
订单相关 order
订单相关的app
投诉相关 tousu
投诉相关的app
不同的功能模块推荐使用不同的app去开发
django支持多app
八、用pycharm去创建Django
注意:在用pycharm去创建Django时一定一定要注意一个Django一个项目
启动方式(停止按Ctrl+c):
第二种启动方式:
修改端口:
修改端口
快捷键(智能创建加提示):
- 创建app以及注册app
在settings中注册APP
用命令行创建的app与用pycharm创建的区别
命令行创建
pycharm创建
九、Django主要的文件功能
mysite
-mysite
--__init__.py
--settings.py 项目配置文件
--urls.py 路由视图函数对应关系 项目的总路由
--wsgi.py
-manage.py
app01
--migrations文件夹 数据库改动记录
----__init__.py
--__init__.py
--admin.py django后台管理
--apps.py 注册app相关
--models.py 模型类(ORM)
--tests.py 测试文件
--views.py 视图函数(******)
app02
--migrations文件夹 数据库改动记录
----__init__.py
--__init__.py
--admin.py django后台管理
--apps.py 注册app相关
--models.py 模型类(ORM)
--tests.py 测试文件
--views.py 视图函数(******)
db.sqlite3 django自带的一个小型用于本地测试的数据库(对日期格式的数据不是很敏感)
十、小白必会三板斧
HttpResponse
返回字符串
render
返回html页面 并且可以给html页面传数据
模板的渲染(将数据在后端按照模板语法放入html对应的位置)
redirect
重定向
def index(request):
return HttpResponse('你好啊 小妹妹')
def login(request):
return render(request,'login.html',{'user_dict':{'username':'jason','password':123},'userxxx':'hello world'})
def home(request):
# return redirect('https://www.mzitu.com')
return redirect('/index')
"""mysite URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), url(r'^login/', views.login), url(r'^home/', views.home), ]
from django.shortcuts import render, HttpResponse, redirect # Create your views here. def index(request): return HttpResponse('你好呀,小妹妹') # 返回字符串使用 def login(request): return render(request, 'login.html', {'user_dict': {'username': 'yafeng', 'password': 123}}) #返回HTML页面 def home(request): # return redirect('https://www.mzitu.com') # 会跳转比如我点击的是home,结果跳到妹子图里面去了 return redirect('/index')
<!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 href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <h1>亚峰你最棒</h1> <a href="/index">index</a> <a href="/login">login</a> {{ user_dict }} {{ user_dict.username }} {% for foo in user_dict %} {% endfor %} {% if user_dict %} {% endif %} </body> </html>
十一、容易犯的错误(*******)
1.代码修改了始终没有效果
1.在同一个端口起了多个服务 一直跑的是最开始的那个服务
2.浏览器缓存问题
*************创建app之后一定一定要先去setting文件中注册**********
django能够自动重启 但是它的重启机制
只要检测到你的代码有变化 在一定的时间间隔内就会自动重启
所以有时候可能会出现 你代码还没写完 就已经自动重启了
Only you can control your future
You're not alone. You still have family,peopel who care for you and want to save you.