MySQL分组
# 概念:分组是按照某个指定的条件将单个单个的个体分成一个个整体
# MySQL分组的关键字:group by
# 分组一般配合聚合函数使用: sum max min avg count
基本的语法格式:
group by 字段名 [having 条件表达式]
# 单独使用 group by关键字时,查询结果会只显示每个分组的第一条记录
# group by关键字可以和group_concat()函数一起使用。group_concat()函数会把每个分组的字段值都显示出来
多字段分组:
即先按第一个字段分组,然后在第一个字段值相同的记录中,再根据第二个字段的值进行分组...一次类推
使用HAVING过滤分组:
having关键字是对分组结果进行过滤。where关键字是对表数据进行过滤,两者同时存在时:肯定是先计算WHERE,WHERE排除的记录肯定是不会出现在分组内的
环境变量
# 概念: 环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息
# 作用:通过在环境变量里面加入所有软件的安装路径,当我们想运行某一软件时双击其快捷方式或者在DOS界面输入软件名称,此时,计算机除了在其当前目录下寻找该软件的.exe文件外,还在环境变量中搜索软件的路径,找到,运行。
# 综上,Windows和DOS操作系统中的path环境变量,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还应到path中指定的路径去找。用户通过设置环境变量,来更好的运行进程。
关于get请求能否携带请求体
# 地址栏中:get,post都能带
# 请求体:post ,get能不能呢?
HTTP协议中没有明确规定GET请求是否能带body,市场上部分浏览器会不支持GET请求带body。HTTP 协议未定义 GET 请求的 body 语义,如果想用 GET 请求发送 body,得先为其定义语义,并确保上下游都能很好的支持。作为服务接口的提供方,不应该假设所有的调用方都能发出 GET 请求 body;作为调用方,不应该假设服务方能完美解析 GET 请求 body。
0.0.0.0和localhost和127.0.0.1 的区别
-127.0.0.1 是本地回环地址,只接受本地机器发起的连接请求。
-0.0.0.0 代表本机上所有的 IP 地址,监听所有相应的网络请求,绑定0.0.0.0有一定安全隐患
0.0.0.0
IPV4中,0.0.0.0地址被用于表示一个无效的,未知的或者不可用的目标
当一台主机还没有被分配一个IP地址的时候,用于表示主机本身,用作默认路由,表示”任意IPV4主机”。
localhost也叫local ,正确的解释是:本地服务器
localhost是个域名,而不是一个ip地址。之所以我们经常把localhost与127.0.0.1认为是同一个是因为我们使用的大多数电脑上都讲localhost指向了127.0.0.1这个地址。
是不经网卡传输,它不受网络防火墙和网卡相关的的限制,一般设置程序时本地服务用localhost是最好的,localhost不会解析成ip,也不会占用网卡、网络资源。
127.0.0.1在windows等系统的正确解释是:本机地址(本机服务器)
是通过网卡传输,依赖网卡,并受到网络防火墙和网卡相关的限制。
有时候用localhost可以,但用127.0.0.1就不可以的情况就是在于此:
猜想localhost访问时,系统带的本机当前用户的权限去访问,而用ip的时候,等于本机是通过网络再去访问本机,可能涉及到网络用户的权限。
总结:
127.0.0.1 是一个环回地址。并不表示“本机”。0.0.0.0才是真正表示“本网络中的本机”。在实际应用中,一般我们在服务端绑定端口的时候可以选择绑定到0.0.0.0,这样我的服务访问方就可以通过我的多个ip地址访问我的服务。
django请求生命周期
1、客户端浏览器向django服务端发送请求之后
2、首先回经过web网关接口,将客户端的请求解析成HTTP格式的数据封装到request对象中,解析后的数据回来到应用程序部分
3、首先会经过django的中间件,django自带了7个中间件,请求来的时候会经过每个中间件中的process_request方法,经过中间件之后才能到达真正的django后端。
4、请求会经过路由层,在进行路由匹配后执行对应的视图函数,在经过视图函数的业务逻辑后会产生response对象,响应对象也会通过中间件中的每个process_response方法,回到web服务网关接口,将response对象打包成HTTP格式的数据返回给客户端浏览器。
中间件题目
写个django项目---中间件
取出用户访问的 user-agent和ip地址,(sqlite,mysql)建个表,存到表汇总
id user-agent ip
myzhong/appMyidd.py from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse,redirect from app01 import models class MyMiddlew(MiddlewareMixin):def process_request(self, request):addr=request.META.get('REMOTE_ADDR')llq=request.META.get('HTTP_USER_AGENT')models.ShuJu.objects.create(ShuJu_REMOTE_ADDR=addr,ShuJU_HTTP_USER_AGENT=llq)def process_response(self, request, response):passreturn response
setting.py 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','myzhong.appMyidd.MyMiddlew', ]
models.py from django.db import models# Create your models here. class ShuJu(models.Model):# title varchar(64) uniqueShuJu_REMOTE_ADDR = models.CharField(max_length=1000, verbose_name='IP')ShuJU_HTTP_USER_AGENT=models.CharField(max_length=2000,verbose_name='浏览器')
http协议补充
# http 基于tcp的---》可靠传输
http协议 0.9版本
客户端----》服务端 建立tcp的链接---》三次握手 客户端给服务端发送消息---》借助于tcp通道 服务端给客户端回消息----》借助于tcp通道 断开tcp的链接----》四次挥手
http 主流 1.1 keep-alive---》时间---》过了时间---》tcp就会断开
客户端同时发送两个http请求 客户端----》服务端 建立tcp的链接---》三次握手 ---第一次请求---- 客户端给服务端发送消息---》借助于tcp通道 服务端给客户端回消息----》借助于tcp通道 ---第二次请求---- 客户端给服务端发送消息---》借助于tcp通道 服务端给客户端回消息----》借助于tcp通道 断开tcp的链接----》四次挥手
http 2.x版本 多路复用
客户端同时发送5个http请求 客户端----》服务端 建立tcp的链接---》三次握手 tcp是流式协议---》一次带了一些数据 【请求1的数据,请求2的数据,请求3的数据,请求4的数据,请求5的数据 】 tcp的响应---》一次性带回来了断开tcp的链接----》四次挥手
http 3.x版本 使用udp+协议 保证了可靠
web框架补充
# web 框架:
别人帮咱们写了一些基础代码,只需要在固定的位置写固定的代码,就能实现一个web应用
Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法。web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了。浏览器和服务器的是基于HTTP协议进行通信的。也可以说web框架就是在以上十几行代码基础张扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率。
# wsgi协议
客户端浏览器 ----------------------> python web框架之间通信需要遵循协议 发出来的是http请求 符合wsgi协议的web服务器 django,flask requset response 基于这个协议的web服务器:
wsgiref:django框架默认就用它,性能低,并发量低,测试阶段使用
uwsgi:c语言写的
gunicorn:python写的wsgi协议规定:
web服务器后面的python框架一定是一个可调用的对象,
必须接收两个参数(environ, start_response)
environ它是个字典,里面全是http请求的东西
# 使用wsgiref写个web服务:
from wsgiref.simple_server import make_serverdef mya(environ, start_response):print(environ)start_response('200 OK', [('Content-Type', 'text/html')])if environ.get('PATH_INFO') == '/index':with open('index.html','rb') as f:data=f.read()elif environ.get('PATH_INFO') == '/login':with open('login.html', 'rb') as f:data = f.read()else:data=b'<h1>Hello, web!</h1>'return [data] # 可调用对象---》能加括号执行的对象 if __name__ == '__main__':myserver = make_server('', 8011, mya) # 请求来了---》经过wsgiref---》调用后面的可调用对象--》传入两个参数(environ, start_response)print('监听8011')myserver.serve_forever()
django概念
# MVC与MTV模型 --->所有web框架其实都遵循mvc架构
MVC:模型(M:数据层),控制器(C:逻辑判断)和视图(V:用户看到的)三层
将代码拆到不同的位置,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求
MTV:M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
T 代表模板 (Template):负责如何把页面展示给用户(html)。
V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template# 补充软件版本:
3.6.小版本 后面小版本只做bug修改
3.7.小版本
# 下载djagno:1.x 2.x 3.x 4.x相关命令:
pip uninstall django #卸载 pip3 install django==3.2.20 pip3 install django # 如果不指定版本就会装最新 django-admin startproject 项目名 # 命令创建 python manage.py runserver 0.0.0.0:8080 # 启动项目
路由控制
# 概念:
URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行
# 使用:path:准确路径,精准匹配,以后基本都是使用path
re_path:就是原来的url,正则匹配,使用的非常少
放在列表中:urlpatterns = [],列表中得数据,必须是 path或re_path执行完的结果
# path详细使用:
path('admin/', login)---》 等价于:_path(route, view, kwargs=None, name=None)
第一个参数(route):准确路径,字符串,转换器
-127.0.0.1:8080/login/justin-path('login/<str:name>', admin.site.urls),
-视图函数中 def login(request,name)path支持五种转换器:str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式int,匹配正整数,包含0。slug,匹配字母、数字以及横杠、下划线组成的字符串。uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
第二个参数: 视图函数的内存地址,不要加括号
路由一旦匹配成功,就会执行你写的这个视图函数(request),并且会把request对象传入
如果有分组的参数[有名,无名],或者转换器的参数,都会被传递到视图函数中作为参数def login(request,name)
第三个参数:kwargs 是给视图函数传递默认参数
第四个参数:路径的别名,后期使用反向解析得到该路径# re_path的详细使用:
第一个参数是正则表达式,其他参数一样
path通过转换器能完成这个操作,后期用的很少,危险性大,原来之所以支持正则的目的是为了分组出参数
# 反向解析:用在视图函数中,用在模板中
没有转换器的情况: path('login/', login,name='login') res=reverse('login') #当时 定义路径传入的name参数对应的字符串 有转换器的情况: path('login/<str:name>', login,name='login') res=reverse('login',kwargs={name:lqz}) #当时 定义路径传入的name参数对应的字符串 生成路径'login/lqz'
# 路由分发
为什么默认路由匹配就匹配到了 urls.py ?
settings.py 有配置的
ROOT_URLCONF = 'django_demo02.urls'
一个app自己有自己的路由,在app下创建urls.py
视图层
views.py 这个文件,目前写的是视图函数
def 视图函数(request):return 四件套
# request对象:
它是http请求,是数据包-字符串形式给拆分成了django中得request对象
常用的:request.path request.method request.GET requets.POST requets.body request.get_full_path() # 方法 request.files # 前端携带文件过来---》转成了字典,根据文件的名字取到文件对象
不常用:
request.META 是一个Python字典,包含了所有本次HTTP请求的Header信息,比如用户IP地址和用户Agent(通常是浏览器的名称和版本号)。
request.cookie request.session request.content_type # 提交的编码格式:urlencoded(form表单),json,form-data,text/plain(一般不用,浏览器默认的格式) request.META: 请求头中得数据user-agent:HTTP_USER_AGENTreferer:客户端ip地址:REMOTE_ADDR用户自定义的 定义:name=lqz取:request.META.get('HTTP_NAME') # 前面加HTTP_ 把自定义的转成大写request.user # authrequest.is_ajax()
# FBV和CBV:
FBV开发模式 全名为:
function based views
, 是一种基于函数的视图调用,他的优点就是简单上手,不需要去继承函数, 所以我们也不需要去阅读很多底层代码,缺点就是不符合python的面向对象的思想, 也就是不可以去继承和多态。# 登录验证 def login(request):message = ""if request.method == "POST":user = request.POST.get('username')pwd = request.POST.get('password')c = Administrator.objects.filter(username=user, password=pwd).count()if c:request.session['is_login'] = Truerequest.session['username'] = userreturn redirect('/index.html')else:message = "用户名或密码错误"return render(request, 'login.html', {'msg': message})
CBV开发模式, 全称为 class based views 是一种基于类的视图函数调用,符合python的面向对象思想, 可以完好的继承和多态, CBV开发模式将各种方式用函数分开,实现了功能的分离, 比如可以直接使用 get(), post() 之类的方法, 同时省去了我们用 if 进行逻辑的判断, 提高了代码的可读性
from django.shortcuts import render,HttpResponse from django.views import Viewclass Login(View):def get(self,request):return HttpResponse("GET 方法")def post(self,request):user = request.POST.get("user")pwd = request.POST.get("pwd")if user == "runoob" and pwd == "123456":return HttpResponse("POST 方法")else:return HttpResponse("POST 方法 1")