一、学习准备
1、下载安装Django(建议安装1.x版本)
方法:终端cmd输入命令:pip install django==1.11.11 然后回车即可
校验是否安装成功:django-admin
注意:如果是python3.7版本安装1.11.11,会报错。安装2.x版本不会
报错信息如下
解决办法:vim进入红框内的文件,将151行的
‘%s=%s’ % (k, v) for k, v in params.items(), 中的,去掉
改成: ‘%s=%s’ % (k, v) for k, v in params.items()
然后在运行就好了
二、纯手撸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 请求头 Host: 127.0.0.1:8080 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 请求体 ' """ while True: conn, addr = server.accept() data = conn.recv(1024) conn.send(b'HTTP/1.1 200 OK ') data = data.decode('utf--8') # 一串字符串 target_url = data.split(' ')[0].split(' ')[1] #判断url返回响应的内容 if target_url == '/index': with open(r'D:python的pycharm正式课day49 emplates 1 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模块
3.基于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 emplates 2 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 emplates 3 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 emplates 4 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页面 并且在该页面上还可以将传递过来的数据当成字典数据进行获取值的操作
模板的渲染
后端将生成好的数据直接传递给某个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.模板语法(是在后端实现的 前端根本不识别)
五、python的web框架介绍
简易版本的web框架请求流程图
python三大主流web框架
django
大而全 自身携带的组件和功能特别特别多 就类似于航空母舰
不足之处:笨重
当你的功能不多 不需要使用很多其他功能
flask(源码600多行 请求上下文 应用上下文)
小而精 自身携带的组件和功能特别特别少 就类似于游骑兵
虽然自身功能比较少 但是第三方支持该框架的模块特别特别多
如果你将flask第三方模块全部叠加起来 甚至可以超过django
不足之处:受限于第三方模块
tornado
异步非阻塞
天然支持高并发 甚至可以用它来开发游戏服务器
A:socket
B:路由分发
C:模板渲染
django
A:用的别人的 wsgiref
B:自己写的
C:自己写的
flask
A:用的被人的 werkzeug
B:自己写的
C:用的别人的 jinja2
tornado
A,B,C都是自己的
六、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 host:port # host不写,django默认的端口号是8000
注意:django1.11.11在python3.7版本下不兼容,会报错,如
解决方案为:
3.创建具有独立功能的app 通常情况下应该做到见名知意
注意:别忘了在setting里注册app
命令行创建
python manage.py startapp app的名字
python manage.py startapp app01
app01
--migrations文件夹
--__init__.py
--admin.py
--apps.py
--models.py
--tests.py
--views.py
注意(*******):
"""
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(对应上面pycharm快捷方式)
注册app (cmd下还是pycharm快捷方式下都需要)
用命令行创建的app与用pycharm创建的区别
1、使用命令行创建的Django项目不会创建templates模板文件夹,只能手动创建
2、命令行创建的Django项目配置文件settings中没有填写路径需要手动添加到环境变量中,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
重定向
可以重定向到自己写的url上可以简写url只写结尾
也可以重定向到指定的url
mysitte_pycreate/urls.py(导入app01模块,添加对应的方法)
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), ]
mysitte_pycreate/settings.py(注册了app)
""" Django settings for mysite_pycreate project. Generated by 'django-admin startproject' using Django 1.11.11. For more information on this file, see https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.11/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'mnn_s3gvkh7ytou2$qe609y-$#5frndo-se-upgd&q_c$pr2&h' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition # 已经安装过的app 我创建的app必须先在这个地方注册之后才能正常执行 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', #注册我们自己的app # 'app01' # 简写 'app01.apps.App01Config' # 完整写法 ] # 中间件 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', ] ROOT_URLCONF = 'mysite_pycreate.urls' # 模板文件夹配置 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'mysite_pycreate.wsgi.application' # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases # 数据库相关的配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/'
templates/login.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> <h1>这是login的html</h1> {{ user_dic.username }} {{ userxxx }} </body> </html>
app01/views.py(定义了方法)
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_dic':{'username':'jason','password':123},'userxxx':'hello world'}) #返回html页面,并且可以给html赋值 #html可以通过{{ }}获取值 def home(request): return redirect('/index')
效果展示:
十一、容易犯的错误(*******)
1.代码修改了始终没有效果
1.在同一个端口起了多个服务 一直跑的是最开始的那个服务
2.浏览器缓存问题
*************创建app之后一定一定要先去setting文件中注册**********
django能够自动重启 但是它的重启机制
只要检测到你的代码有变化 在一定的时间间隔内就会自动重启
所以有时候可能会出现 你代码还没写完 就已经自动重启了