Ⅰ 环境变量和python多版本共存
【一】环境变量
【1】什么是环境变量
- 无论是win,mac,linux 都有环境变量的概念,以win为例什么是环境变量?
- 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息
【2】win如何配置环境变量
我的电脑-->右键属性-->高级系统设置-->环境变量
有两套:win,mac, linux都一样
用户环境变量:操作系统是分用户,用户环境变量配置的只针对于当前用户
如果换了其他用户登录进来,用不到别的用户的环境变量的
系统环境变量:针对于操作系统,不分用户
所有用户进来,都会有相应的环境变量
【3】 打印出环境变量(你环境变量已有的让其在cmd打印出)
- 打开Terminal,cmd
- mac,linux输入 : echo $MS_PWD
- win输入 : echo %MS_PWD%
【4】在环境变量中有个非常重要的参数:PATH (重点)
里面放了很多路径
win: 以 ; 分割
mac,linux :以 : 分割
这堆路径的作用:
以后在命令行中敲一个命令(xx.bat,xx.exe),命令是否会执行
先在当前目录下查找这个命令,如果能找到,直接就执行了(比如cd)
如果找不到,会按照 PATH配置的目录,从上往下(前往后),依次查找,找到就执行
如果还找不到,就报错,说:不是内部或外部命令,也不是可运行的程序
或批处理文件。
-如果PATH的环境变量中 的目录中,有多个同名的 【可运行的程序】,会先运行前面的,后面的就运行不了
【5】如果向让一个可执行文件,在任意路径下都能执行,必须把它所在路径加入环境变量PATH
-比如:django-admin 创建django项目
-E:\python\python310\Scripts\ 在环境变量PATH中,django-admin.exe
-E:\python\python310\ 在环境变量PATH中,python.exe
-E:\python\python310\Scripts\ 在环境变量PATH中,pip.exe
-mysql 客户端链接数据库
-E:\MYSQL8\mysql-8.4.2-winx64\bin 在环境变量PATH中 mysql mysqld
【二】python多版本共存 (简易介绍及其操作)
【1】下载安装包
为了测试,我下载版Python2.x和Python3.x版本,下载地址:https://www.python.org/downloads/
【2】安装python版本兼容的原理
安装多个版本的方法就是避免变量重名的情况,比如python2.x和python3.x版本安装完毕后都有默认的python执行脚本和一个pip的脚本,我们只需要在path环境中让他们找到各自的脚本名称就可以轻松实现多版本安装啦!
【3】配置Python2.x的环境变量
(1)安装完毕后将服务python脚本进行改名操作
(2)删除python2.x版本自带的脚本
(3)将python2.x加入windows系统的环境变量中
【4】安装Python3.x
(1)安装完毕后将服务python脚本进行改名操作
(2)删除Python3.x版本自带的脚本
- 重复2.x版本步骤
(3)将python2.x加入windows系统的环境变量中
【4】在cmd中分别运行两个版本python
- python2跟python3
Ⅱ 视图层源码分析
【一】两个视图基类
# APIViwe
【1】 继承自django的View,必须写 get,post,delete。。。
【2】 类属性:parser_class,render_class
使用顺序是:视图类自己-->项目配置文件-->drf内置配置
render_class=api_settings.DEFAULT_RENDERER_CLASSES
api_settings是drf的配置,如果自己项目配置文件配了 REST_FRAMEWORK={},会覆盖掉原来drf默认的配置
【3】 读APIViwe-->as_view和dispatch
# 能从里面得到
(1) 包装了新的request:
新的request对象:request._request
视图类的对象 :self.requset 就是新的request
(2) 去除了csrf认证
csrf_exempt(view)
(3) 做了三大认证:认证,权限,频率
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
(4) 做了全局异常处理:后续要了解定制返回格式
在try里
【4】 总结:
def get(self,request):
# request 新的
# csrf校验没了
# 执行完三大认证,才能到这里
# 出了异常,会有捕获
request._request
self.request=request
# GenericAPIView
【1】 继承了APIView--->APIView具备的所有特点,它都有,GenericAPIView更多一些
【2】 多了几个类属性
queryset # 数据源,直接给列表 或 QuerySet
serializer_class # 序列化类
lookup_field = 'pk' # get_object,根本没传参数,但它指定是按pk拿
lookup_url_kwarg = None #lookup_url_kwarg=1
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS # 过滤
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS # 分页
【3】 多了几个方法:
get_queryset:本质就是返回了self.queryset 数据源
def get_queryset(self):
queryset = self.queryset
if isinstance(queryset, QuerySet):
queryset = queryset.all() # 因为self.queryset 会先执行-->为了保证数据最新
return queryset
get_serializer:直接实例化得到序列化类的对象-->self.serializer_class
def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs)
def get_serializer_class(self): # 通过重写它,定制序列化,反序列化使用不用序列化类
return self.serializer_class
# 总结:
内部方法中拿序列化类的对象:get,post-->都是通过self.get_serializer()
但是我们可以通过【重写】get_serializer_class,返回不同序列化类来控制:self.get_serializer()拿到的序列化类不同
# 例如
# 要求,序列化用 BookSerialzier 序列化类,反序列化用 BookWriteSerialzier
class BookView(ListCreateAPIView):
queryset = Book.object.all()
serializer_class = BookSerialzier
def get_serializer_class(self):
if self.request.method=='GET':
return BookSerialzier
else:
return BookWriteSerialzier
get_object:根据 lookup_field 指定的对应参数,从数据源中 过滤出单个对象
def filter_queryset(self, queryset): # 过滤用的,后面了解
XX_paginated_xx # 跟分页相关,后面了解
- GenericAPIView的源码数据
【二】5个视图扩展类
# CreateModelMixin # GenericAPIView+create方法-->新增记录
class CreateModelMixin:
def create(self, request, *args, **kwargs):
# 拿到序列化类,实例化得到对象
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer) # 把它单独封装成方法的目的?
# 通过重写 perform_create 在保存直接或之后干xx事
return Response(serializer.data, status=status.HTTP_201_CREATED)
def perform_create(self, serializer):
# 之前干的事
serializer.save()
# 之后干的事
ListModelMixin::list
-获取所有
DestroyModelMixin:destroy
-删除
-perform_delete
RetrieveModelMixin:retrieve
-拿单条
UpdateModelMixin:update
-更新
-perform_update
【三】9个视图子类
CreateAPIView:
-GenericAPIView+CreateModelMixin+post方法
-只写一个新增接口
class BookView(CreateAPIView):
queryset=xx
serializer_class=yy
def perform_save(self):
pass
def get_serializer_class(self):
return zz
-ListAPIView:
-GenericAPIView+ListModelMixin+get方法
-只写一个查询所有接口
class BookView(ListAPIView):
queryset=xx
serializer_class=yy
-DestroyAPIView:
-GenericAPIView+DestroyModelMixin+delete方法
-UpdateAPIView:
-GenericAPIView+UpdateModelMixin+put方法
-RetrieveAPIView:
-GenericAPIView+RetrieveModelMixin+get方法
-ListCreateAPIView:
-GenericAPIView+ListModelMixin+CreateModelMixin+post方法+get方法
-写一个查询所有接口和新增接口
class BookView(ListCreateAPIView):
queryset=xx
serializer_class=yy
-RetrieveUpdateDestroyAPIView
-GenericAPIView+RetrieveModelMixin+UpdateModelMixin++DestroyModelMixin+put方法+get方法+delete方法
-写一个查询单条,修改一条,删除一条
class BookView(RetrieveUpdateDestroyAPIView):
queryset=xx
serializer_class=yy
-RetrieveDestroyAPIView,
-RetrieveUpdateAPIView
【四】视图集
# ModelViewSet,ReadOnlyModelViewSet, ViewSetMixin, ViewSet,GenericViewSet
# ModelViewSet:5个接口都有里面没有get,post,delete方法了,因为路由写法变了,是映射的
CreateModelMixin
ListModelMixin
DestroyModelMixin
RetrieveModelMixin
UpdateModelMixin
GenericViewSet
-GenericAPIView
-ViewSetMixin
#ReadOnlyModelViewSet:查询单条和所有接口
ListModelMixin
RetrieveModelMixin
GenericViewSet
-GenericAPIView
-ViewSetMixin
# ViewSetMixin:控制路由写法变了的类。以后只要路由写法变了,必须继承它
-重写了as_view,必须传字典做映射的方式,否则报错
-原理是通过反射:实现了MyViewSet.as_view({'get': 'list', 'post': 'create'})
-要执行get的时候,本质执行的是 list
-好处,以后视图类,可以写任意名字的方法,只要路由做好映射即可
-路由:path('send_sms/', UserView.as_view({'get':'send_sms'})),
-视图类:
class UserView(ViewSetMixin,APIView):
def send_sms(self):
print('真发短信')
return Response({'code':100,'msg':"短信发送成功"})
# ViewSet= ViewSetMixin,APIView
# GenericViewSet=ViewSetMixin+GenericAPIView
# 登录
from rest_framework.response import Response
class UserDetailView(GenericViewSet):
serializer_class = 某个序列化类
def login(self):
serializer=self.get_serializer()
serializer.is_valiad()
return Response({'code':100,'msg':"短信发送成功"})
Ⅲ 视图层总结-小案例选择哪些视图类继承
# 【1】 发送短信接口
-APIView+get方法
-ViewSet+send_sms方法
# 【2】 查询所有,查询单条
-路由:
path('books/', BookView.as_view({'get':'list'})),
path('books/<int:pk>', BookView.as_view({'get':'retrieve'})),
-视图类
class BookView(ReadOnlyModelViewSet):
queryset=
serializer_class=
# 【3】 查询所有,删除一条
-写俩:ListAPIView DestroyAPIView
-写一个:
-路由:
path('books/', BookView.as_view({'get':'list'})),
path('books/<int:pk>', BookView.as_view({'delete':'destroy'})),
-视图类
class BookView(GenericViewSet,ListModelMixin,DestroyModelMixin):
queryset=
serializer_class=
# 【4】 总结
1 只要向路由变了:ViewsetMixin
2 只要想序列化,反序列化,就用GenericAPIView
3 即想路由变了又想序列化,反序列化 GenericViewSet
4 即想路由变了又想序列化,反序列化 ,还想写某一个或某几个接口 GenericViewSet+5个视图扩展类
Ⅳ 路由层
【一】继承 ViewSetMixin
# 只要继承 ViewSetMixin 的子类--->路由写法就变成了
变成映射方式
【二】 drf提供了两个视图类,实现,不用映射,直接通过类 实例化得到对象方式,自动注册路由
# 【1】 导入一个类
from rest_framework.routers import SimpleRouter,DefaultRouter
# 【2】 类实例化得到对象
router=DefaultRouter()
# 【3】 注册视图类
router.register('books',BookView,'books')
# 【4】 在总路由中注册
方式一:
urlpatterns = [
path('', include(router.urls)), # 方式一:把自动生成的路由注册进总路由
]
方式二:urlpatterns+=router.urls
from django.contrib import admin
from django.urls import path, include
from .views import BookView,PublisherView
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('books',BookView,'books') # 自动映射 'get': 'list', 'post': 'create' 'get': 'retrieve', 'put': 'update', 'delete': 'destroy'
# router.register('publishers',PublisherView,'publishers')
print(router.urls)
# [<URLPattern '^books/$' [name='books-list']>,
# <URLPattern '^books\.(?P<format>[a-z0-9]+)/?$' [name='books-list']>,
# <URLPattern '^books/(?P<pk>[^/.]+)/$' [name='books-detail']>,
# <URLPattern '^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$' [name='books-detail']>,
# <URLPattern '' [name='api-root']>,
# <URLPattern '<drf_format_suffix:format>' [name='api-root']>]
# from app01.views import UserView
urlpatterns = [
# path('books/', BookView.as_view({'get': 'list', 'post': 'create'})),
# path('books/<int:pk>/', BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
# path('', include(router.urls)), # 方式一:把自动生成的路由注册进总路由
]
urlpatterns += router.urls # 方式二
【三】 DefaultRouter 和SimpleRouter 区别
DefaultRouter 生成路径更多-->生成一个根
SimpleRouter 则会直接报错
- DefaultRouter
- SimpleRouter
【四】action装饰器
# 导入
from rest_framework.decorators import action
# 使用
@action(methods=['methods'],detail=False)
# 装饰器源码 def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
@action()
action装饰器可以接收两个参数:
methods: 声明该action对应的请求方式,列表传递
# methods=请求方式,可以有多个,
detail: 声明该action的路径是否与单一资源对应,及是否是xxx/<pk>/action方法名/
True 表示路径格式是xxx/<pk>/action方法名/
False 表示路径格式是xxx/action方法名/
# 如 False: api/v1/books/login/ True: api/v1/books/4/login/ 用的少
url_path=None # 路径名字,不写默认以方法名,如果 url_path=aa ---》api/v1/books/aa/
url_name=None # 反向解析用,不用了
【五】继承了ViewSetMixin ,视图类中可以定义跟请求方式不同名的方法做映射(重点)
- models.py
from django.db import models
# Create your models here.
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
- app01\urls.py
from django.contrib import admin
from django.urls import path, include
from .views import BookView,PublishView
from rest_framework.routers import DefaultRouter,SimpleRouter
router = DefaultRouter()
router.register('books',BookView,'books') # 自动映射 'get': 'list', 'post': 'create' 'get': 'retrieve', 'put': 'update', 'delete': 'destroy'
router.register('publish',PublishView,'publish')
print(router.urls)
# [<URLPattern '^books/$' [name='books-list']>,
# <URLPattern '^books\.(?P<format>[a-z0-9]+)/?$' [name='books-list']>,
# <URLPattern '^books/(?P<pk>[^/.]+)/$' [name='books-detail']>,
# <URLPattern '^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$' [name='books-detail']>,
# <URLPattern '' [name='api-root']>,
# <URLPattern '<drf_format_suffix:format>' [name='api-root']>]
# from app01.views import UserView
urlpatterns = [
# path('books/', BookView.as_view({'get': 'list', 'post': 'create'})),
# path('books/<int:pk>/', BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
# path('', include(router.urls)), # 方式一:把自动生成的路由注册进总路由
path('', include(router.urls)), # 方式一:把自动生成的路由注册进总路由
]
urlpatterns += router.urls # 方式二
- serializer.py
from .models import Book
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
# exclude=['id','name'] exclude 的意思是不包括哪些字段
- views.py
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializer import BookSerializer
from rest_framework.decorators import action
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
print('登陆成功')
return Response({'code': 200, 'msg': '登陆成功'})
class PublishView(ModelViewSet):
# api/v1/publish/send_sms/--->post请求就会触发它执行
@action(methods=['POST'], detail=False)
def send_sms(self, request):
print('发送短信成功')
return Response({'code': 100, 'msg': '发送短信成功'})
【六】在 视图类的对象中,有action参数,sele.action就是方法名的字符串
- models.py
from django.db import models
# Create your models here.
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
- urls.py
from django.contrib import admin
from django.urls import path, include
from .views import BookView
from rest_framework.routers import DefaultRouter,SimpleRouter
router = DefaultRouter()
router.register('books',BookView,'books') # 自动映射 'get': 'list', 'post': 'create' 'get': 'retrieve', 'put': 'update', 'delete': 'destroy'
urlpatterns = [
path('', include(router.urls)), # 方式一:把自动生成的路由注册进总路由
]
urlpatterns += router.urls # 方式二
- serializer.py
from .models import Book
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
# fields = '__all__'
exclude=['id','name'] # exclude 的意思是不包括哪些字段
class BookWriteSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
- views.py
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializer import BookSerializer
# 序列化和反序列化用不同序列化类
from rest_framework.decorators import action
from .serializer import BookWriteSerializer
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get_serializer_class(self):
if self.action == 'list' or self.action == 'create':
return BookSerializer
elif self.action == 'retrieve' or self.action == 'destroy' or self.action == 'update':
return BookWriteSerializer
elif self.action=='login':
return BookSerializer
@action(methods=['POST'], detail=False)
def login(self, request):
print('登录成功')
return Response({'code': 100, 'msg': '登录成功'})
标签:get,python,self,视图,环境变量,源码,import,class,serializer
From: https://www.cnblogs.com/zyb123/p/18333336