# 开发环境: windows开发(主流),sanic,fastapi框架,windows安装不上(不支持)
# 远程连接linux开发,远程连接linux内的docker开发
编译型
c:c代码写完,编译(不同平台),跨平台运行,linux源码安装软件,自行编译,运行
java:一处编码,处处运行,java是编译型还是解释型?编译型,编译过程--- 把java源代码编译成字节码文件 .class --->不能直接运行在操作系统之上---> 必须运行在jvm(java虚拟机),jvm运行至少300m内存
jdk
jre
jvm
javase javame javaee
go: 编译型, 跨平台编译(windows平台可以编译出mac平台的可执行文件),所有go代码打成一个执行文件
解释型
python: 强类型动态语言 (int+str 不行,不能直接相加)
js:弱类型动态语言,只能在浏览器中运行,nodejs
php:web开发
# 方向:
1. python后端开发:做网站,前端可以是app,小程序的python后端
2. 自动化运维:收集软硬件信息(cmdb),jumpserver(堡垒机),sql审批,监控,日志收集,处理
3. 自动化测试:selenium,appnium,pytest
4. 数据分析
5. 爬虫
6. 量化交易
7. 人工智能
8. 安全方向:端口扫描,弱口令扫描,sql注入,csrf攻击,xss攻击(运用python称为顶级黑客)
9. 网络方向
10. 物联网方向
数据类型
python中一切皆对象
type和object的关系
1. type是object的类
2 type继承了object
3. type是type自己的类
4. object也是由type实例化得到
# a = 2 # b = int(2) # # int是一个类,具体实现是由c语言实现的,如果写了pass,看不到源码,有一部分可以看到 # print(a==b) # # from django.views import View # # print(type(1)) # int: 数字1的type是int # print(type(int)) # print(type(str)) # print(type(dict)) # # # int,dict,str... 都是type类的对象,又继承了object # # type和object是什么关系? # print(type(object)) # print(type(type)) def a(): pass print(type(a))
深浅拷贝
一切皆对象的好处
不同类型之间的变量直接可以相互赋值
a = 100
a = 'xxx'
其实本质,变量都是指向了一个内存地址
出现了深浅copy的问题
l = [1,2,3,[4,5,6]] l2 = l # 赋值 print(l2 is l) import copy # l3 = copy.copy(l) # print(l) # print(l3 is l) # l3[3][1] = 999 # print(l) # print(l3) # l4 = copy.deepcopy(l) # l4[3][1] =999 # print(l) # print(l4) print(type(int)) # type print(type(object)) # type print(type(type)) # type # 所有类,除了object都继承自object,包括type
可变类型和不可变类型
可变类型: 字典,列表,集合
不可变类型: 数字,字符串,元组
字典的key必须用不可变类型
python中函数的参数传递是值传递还是引用传递
python中参数传递都是copy一份传递过去,由于一切皆对象,都是地址,python中区分可变和不可变类型,可变类型在函数中修改会影响原来的,不可变类型不会影响原来的
字符编码
计算机的计量单位:
bit 比特位: 0或者1的一个小格
8个bit为是一个byte,一个字节
1024个字节是1Kb
1024Kb是1mb
1024mb是1gb
1个字节 2的8次方种变化,就可以表示出所有的字符(数字,字母,标点符号)
计算机到了中国 ---> 中国汉字 ---> gbk 编码
但是到了不同国家,不同国家有不同国家编码方式,就会出现乱码问题
unicode编码统一了,字符和数字的对应关系
utf-8: 目前主流的编码存储方式
utf-16
需要说清楚: ASCII码,GBK,UNICODE,UTF-8的关系
闭包函数
1. 定义在函数内部
2. 对外部作用域有引用
函数是一等公民: 函数可以赋值给一个变量
def wrapper(func): def inner(*args,**kwargs): # 代码 print('decorator enter') res = func(*args,**kwargs) print('decorate exit') return res return inner # def a(): # print('xxx') # 没有语法糖 # a = wrapper(a) # a() # 有语法糖 def a(): print('xxx') a()
python中的魔法方法
__init__: 类实例化会触发
__str__: 打印对象会触发
__call__: 对象加括号的时候触发
__new__: 在类实例化时触发,它比__init__早(造出雏形的人,__init__完善人)
__del__: del对象,对象回收的时候触发
__setattr__,__getattr__:(拦截方法),当对象,属性 -->赋值时会调用setattr,如果是取值会调用getattr
__getitem__,__setitem__:
# class Person: # def __init__(self,name): # self.name = name # # def __setitem__(self, key, value): # # self.__dict__[key]= value # setattr(self,key,value) #反射 # # def __getitem__(self, item): # return getattr(self,item,'没有值') #反射取值 # # p = Person('jeffrey') # print(p.name) # p.name = 'daisy' # print(p.name) # # p['name'] = 'jiujiu' # print(p.name) # print(p['name']) dic = {'name': 'jeffrey', 'age': 20} class Mydic(dict): # pass # def __setitem__(self, key, value): # self.__dict__[key] = value # # def __getitem__(self, item): # return self.__dict__[item] # pass def __setattr__(self, key, value): print('对象+点赋值会触发我',key,value) self.__dict__[key] = value def __getattr__(self, item): print('对象+点取值,会触发我') return self[item] # # def __getattr__(self, item): # return self.__dict__[item] mydic = Mydic(name='jeffrey', age=20) print(mydic.__dict__) # print(mydic['name']) # print(mydic['age']) # mydic.name = 99 mydic.name = '555' print(mydic.__dict__) print(mydic.name)
__repr__
__enter__和__exit__ 上下文管理器
class Person(object): def __init__(self,name): self.name = name def __enter__(self): print('我在with管理的时候会触发') print('进入with语句块时执行此方法,此方法如果有返回值会赋值给as声明的变量') return self.name def __exit__(self, exc_type, exc_val, exc_tb): print('用完了会执行我了') print(exc_type) print(exc_val) print(exc_tb) with Person('jeffrey') as p: # 这句话执行,会触发类的__enter__方法 print(p) # 当缩进完了,会触发 __exit__执行
cookie, session, token
http协议:无状态,无链接,基于请求响应,基于tcp/ip,应用层协议
mysql: c/s架构:底层基于socket,自己封装的协议,mysql的客户端:navicat(c++图形化界面,实现了请求和和响应协议),pymysql(用python语言实现了请求和响应协议)
redis:c/s架构,底层基于socket,自己封装的协议
docker: c/s架构,基于http协议,使用restful规范
elasticsearch:c/s架构,基于http协议,使用restful规范
cookie:是存在于浏览器上的键值对,向服务端发送请求,携带它过去(不安全)
session:存在于服务端的键值对(放在哪?内存,文件,mysql,redis)
缺陷:如果用户量很大,存储需要耗费服务器资源
token:就是个字符串(既安全,又存个人信息),加密字符串,会有个人信息
token现在应用非常广泛,契合了前后端分离
JWT: json web token
django中的session底层原理
在中间件中,请求走的时候,process_response,取出request.session的modify属性,判断是否为true, 如果是true,表示在视图函数中修改过session,数据库同步修改,如果是false,就不修改,返回给前端
sessionid:随机字符串
请求来了,通过sessionid,取出随机字符串-> 到数据库中查 -> 把表的数据转成字典,赋值给request.session,后面视图函数中就可以操作它了
异常处理
try: print('xxx') # print(1/0) except Exception as e: print(e) else: # 基本上不会用到 print('正常执行,没有出异常,会走') finally: #无论是否有异常,都会走 print('我是finally')
pymysql的使用
import pymysql # 连接数据库 conn = pymysql.connect(user='root', # The first four arguments is based on DB-API 2.0 recommendation. password="", host='127.0.0.1', database='test', port=3306, ) print(conn) # 获取游标 # cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 查出来数据是字典格式 cursor = conn.cursor() # 查出来数据是字典格式 # 操作 定义一个sql # sql = 'select id,name from book' # sql = 'insert into book (id,name) values (%s,%s)' # cursor.execute(sql,(5,'daisy')) # conn.commit() # ret = cursor.fetchall() # print(ret) # cursor = conn.cursor() # 查出来数据是字典格式 # # 操作 定义一个sql # sql = 'select id,name from book' # cursor.execute(sql) # ret = cursor.fetchall() # print(ret) # 删除 # sql = 'delete from book where name =%s' # cursor.execute(sql,'jeffrey') # conn.commit() sql = 'update book set name = %s where name =%s' cursor.execute(sql,('xxx','daisy')) conn.commit()
django回顾
ip+端口号唯一确定一个应用
web框架是什么
http协议
模板文件是在什么时候完成渲染的
路由控制
django是一个同步框架
# 最新版本3.x
url与要为该url调用的视图函数之间的映射表
1.x 和 2.x 版本路由稍微不同
1.x:url,
2.x:path,,re_path(原来的url)
from django.urls import path, re_path urlpatterns = [ re_path(正则表达式 views视图函数,参数,别名), ]
APPEND_SLASH = True 的用法
有名分组
re_path(r'^articles/(?P<year>[0-9]{4})/$',views.year_archive),无名分组
re_path(r'^articles/([0-9]{4})/$',views.year)
路由分发
path('app01/',include(urls))反向解析
视图函数中
from django.shortcuts importreverse def home(request): print(request.headers) # print(name) url = reverse('homehomehome') print(url) return HttpResponse('ok') #homehomehome是在url配置的别名
在模板中使用
{% url 'homehomehome' %}
名称空间(了解)
2.x的path 内置了几个转换器
str,匹配除了路径分隔符(/)之外的费控字符串,这是默认的形式
int, 匹配正整数,包括0
slug, 匹配字母,数字以及横杠,下划线组成的字符串
uuid, 匹配格式化的uuid
path, 匹配任何费控字符串,包含了路径分隔符(/)
2.x的path 自定义转换器 (了解)
视图层
response对象: 三件套 + JsonResponse 本质都是HttpResponse
HttpResponse
render
redirect
request对象
request.GET: get请求里问号后面的东西
request.POST: urlencoded, formdata 两种编码的数据会被放在这个字典中
request.META: HTTP请求的其他东西,放在里面,如客户端ip地址:remote_addr
request.Files: 上传的文件
request.session: 用的session
JsonResponse
CBV和FBV
文件上传(form 表单中指定编码方式)
def home(request): if request.method == 'POST': print(request.FILES) myfileObj = request.FILES.get('myfile') # 文件对象 # print(type(myfileObj)) # print(myfileObj.field_name) # print(myfileObj.size) name = myfileObj.name with open(name,'wb') as f: for line in myfileObj: f.write(line) return HttpResponse('文件上传成功') return render(request,'home.html',locals())
模板层
模板语法重点:
变量:{{变量名}}
1 深度查询 用句点符
2 过滤器
标签: {{%%}}
内置过滤器: {{ obj | filter__name: param}} 变量名字|过滤器名称:变量
重点: safe
xss攻击
'<a href="https://www.baidu.com">点我</a>' 如果原封不动的显示在html中,一定是a标签html的特殊字符
for标签
if标签
with标签
模板的导入和继承
include
extend: 先用 {%block title%},再用{% extends 'base.html' %} {%block content %} 自己的内容{% end block %}
模型层
使用orm的步骤
1. 在settings中配置(连数据库的地址,端口等)
2. 在__init__.py中使用pymysql
3. 在models.py中写类,写属性
4. 使用:数据库迁移的两条命令
python manage.py makemigrations # 记录
python manage.py migrate # 真正的数据库同步
5. 在视图中使用orm
forms组件
1 使用字段校验功能
1. 写一个类(UserForm),继承Form
2. 在类中写字段, pwd = forms.CharField(max_length=32,min_length=4)
3. 在视图函数中使用 form = UserForm(校验的字典/request.POST)
4. form.is_valid() 通过了,就可以存起来,不通过,forms.errors会有错误信息
2 默认的校验规则还不够,需要自己写钩子函数
局部钩子:
def clean_字段名(self): val = self.cleaned_data.get('name') #val就是要校验的字段,做限制 通过直接return 不通过抛出 raise ValidationError('该用户已注册')
全局钩子
def clean(self): pwd = self.cleaned_data.get('pwd') r_pwd = self.cleaned_data.get('r_pwd') if pwd and r_pwd: if pwd == r_pwd: return self.cleaned_data else: raise ValidationError('两次密码不一致') else: return self.cleaned_data
forms组件源码
入口
form.is_valid() # 内部起了一个for循环,先去校验每个字段配置的规则,校验完成,走该字段的局部钩子函数。一个一个执行完(校验完)会走全局钩子,self就会有clean_data和errors self.errors self.full_clean() self._clean_fields() # 局部字段的校验(自己和局部钩子) if hasattr(self,'clean_%s'%name) value = getattr(self,'clean_%s'%name)() self.cleaned_data[name] = value self._clean_form() #全局的钩子 self._post_clean()
cookie与session组件
# 使用django放置cookie response.set_cookie(key,,value) #(Httpresponse对象) render, JsonResponse,redirect, HttpResponse response.set_signed_cookie(key,value,salt='加密盐')
key, value='', max_age=None
# 删除cookie response.delete_cookie('user') # 获取cookie request.COOKIES['key'] # 获取cookie从request对象 request.COOKIES.get('key')
# session取值与设置值 request.session['k1'] request.session.get('k1',None) request.session['k1']=123 request.session.setdefault('k1',123) del request.session['k1'] # 会话session的key request.session.session_key request.session.clear_expired
中间件组件
process_request(self,request) return response(不再往后走,直接就回去了) return None (会继续往后走) process_response(self,request,response) response return response(否则报错)
进来的时候,从上往下执行
出去的时候,从下往上执行
auth模块
authenticate() login(HttpRequest,user) logout(request) is_authenticated() login_required() create_user() create_superuser() check_password(password) set_password(password) # 扩展auth_user表 # 自己写一个类,继承AbstractUser,自己写扩展字段 在settings中配置: AUTH_USER_MODEL = 'app名.UserInfo'