作业讲解
Views.py
from django.shortcuts import render
# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Author
from .serializer import AuthorSerializer
class AuthorsView(APIView):
def get(self,request):
author_list = Author.objects.all()
ser = AuthorSerializer(instance=author_list,many=True)
return Response({'code':100,'msg':'查询成功','data':ser.data})
def post(self,request):
ser = AuthorSerializer(data = request.data)
if ser.is_valid():
ser.save()
return Response({'code':100,'msg':'创建成功'})
else:
return Response({'code':100,'msg':'创建失败','errors':ser.errors})
class AuthorsDetail(APIView):
def get(self,request,pk):
author_obj = Author.objects.filter(pk=pk).first()
ser = AuthorSerializer(instance=author_obj)
return Response({'code':100,'msg':'查询成功','data':ser.data})
def put(self,request,pk):
author_obj = Author.objects.filter(pk=pk).first()
ser = AuthorSerializer(data = request.data,instance=author_obj)
if ser.is_valid():
ser.save()
return Response({'code':100,'msg':'修改成功'})
else:
return Response({'code':100,'msg':'修改失败','errors':ser.errors})
def delete(self,request,pk):
author_obj = Author.objects.filter(pk=pk).first()
AuthorDetail.objects.filter(pk = author_obj.author_detail_id).delete()
return Response({'code': 100, 'msg': '删除成功'})
Serializer.py
from rest_framework import serializers
from .models import Author,AuthorDetail
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['name','phone','email','age']
email = serializers.CharField(source='author_detail.email')
age = serializers.IntegerField(source='author_detail.age')
def create(self, validated_data):
print(validated_data) # {'name': 'nanananana', 'phone': '18085209', 'author_detail': {'email': '863942169@qq.com', 'age': 24}}
author_detail = validated_data.pop('author_detail')
print(validated_data) # {'name': 'nanananana', 'phone': '18085209'}
res = AuthorDetail.objects.create(**author_detail)
validated_data['author_detail'] = res
author = Author.objects.create(**validated_data)
return author
def update(self, author, validated_data):
print(validated_data) # {'name': 'nanananana', 'phone': '18085209', 'author_detail': {'email': '863942169@qq.com', 'age': 24}}
author.name = validated_data.get('name')
author.phone = validated_data.get('phone')
author.save()
author.author_detail.email= validated_data.get('author_detail').get('email')
author.author_detail.age = validated_data.get('author_detail').get('age')
author.author_detail.save()
return author
模块与包的使用
1.模块:一个py文件,被别的py文件导入使用,这个py文件称之为模块,运行的这个py文件称之为脚本文件
2.包:一个文件夹下有__init__.py
3.总结:
1.导入模块有相对导入和绝对导入,绝对的路径是从环境变量开始的
1.相对导入:. .. (考虑执行文件为准)
2.绝对导入:from ... import ...
2.导入任何模块,如果使用绝对导入,都是从环境变量开始导入起
3.脚本文件执行的路径,会自动加入环境变量
4.相对导入的话,是从当前py文件开始计算的
5.以脚本运行的文件,不能使用相对导入,只能用绝对导入
ps:在统一文件下用相对导入,不同文件下用绝对导入,脚本运行文件不能使用相对导入
反序列化校验源码分析
1.序列化类的校验功能
1.局部钩子:validate_字段名
2.全局钩子:validate
2.思考:为什么在校验局部钩子和全局钩子的时候必须使用:validate_字段名,validate方法名 ---->源码
3.入口:ser.is_valid() ---> 做的校验
继承顺序:AuthorSerializer --->ModelSerializer --->Serializer --->BaseSerializer --->Field
"""
补充:
OOP:面向对象编程
AOP:面向切面编程:在程序的前期,中期,后期插入一些代码来执行
装饰器:实现aop的一种方式
钩子函数:实现aop的一种方式
写在类中的方法,只要写了,就会执行,不写就不执行
"""
1.ctrl+鼠标点:is_valid()
def is_valid(self, *, raise_exception=False):
# 此时还没有validated_data,validated_data是校验成功后的数据,只有执行完才有
if not hasattr(self, '_validated_data'):
try:
self._validated_data = self.run_validation(self.initial_data)
# self.run_validation(self.initial_data):核心,此时按住ctrl+鼠标点击是不对的--->ctrl+鼠标点击只能找当前类的父类,即Field---->正确做法:应该从根上找(self)--->发现Serializer里面有run_validation()方法
except ValidationError as exc:
self._validated_data = {}
self._errors = exc.detail
else:
self._errors = {}
if self._errors and raise_exception:
raise ValidationError(self.errors)
return not bool(self._errors)
ps:self.run_validation(self.initial_data):核心,此时按住ctrl+鼠标点击是不对的--->ctrl+鼠标点击只能找当前类的父类,即Field---->正确做法:应该从根上找(self)--->发现Serializer里面有run_validation()方法
2.在Serializer里找到run_validation()方法(AuthorSerializer、ModelSerializer里都没有这个方法)
def run_validation(self, data=empty):
value = self.to_internal_value(data) # 局部钩子,在Serializer里找到run_validation()方法(AuthorSerializer、ModelSerializer里都没有这个方法)
try:
self.run_validators(value)
value = self.validate(value) # 全局钩子,BookSerializer只要写了,优先执行它的
assert value is not None, '.validate() should return the validated data'
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
return value
ps:
1.value = self.to_internal_value(data):在Serializer里找到to_internal_value()方法(AuthorSerializer、ModelSerializer里都没有这个方法),鼠标点进去
3.ctrl+鼠标点:to_internal_value(data)--->Serializer类的方法
def to_internal_value(self, data):
for field in fields: # fields是序列化类中写的一个个的类字段的对象列表,一个field是name对象,field.field_name字符串:name
validate_method = getattr(self, 'validate_' + field.field_name, None) # self是序列化类的对象,BookSerializer的对象 validate_name
try:
validated_value = field.run_validation(primitive_value) # 字段自己的校验
if validate_method is not None:
validated_value = validate_method(validated_value) # 局部钩子
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = get_error_detail(exc)
except SkipField:
pass
else:
set_value(ret, field.source_attrs, validated_value)
if errors:
raise ValidationError(errors)
return ret
总结
1.入口:ser.is_valid
2.在Serializer里找到run_validation()方法(AuthorSerializer、ModelSerializer里都没有这个方法)
3.走局部钩子的代码:是通过反射获取BookSerializer中写的局部钩子函数,如果写了,就会执行
4.走全局钩子代码:self.validate(value),只要序列化类中写了,优先走自己的
断言
1.断言:断定某个东西是我认为的,如果不是就抛异常(等同于if判断+抛异常)
2.例子
def func(a,b):
return a+b
res = func(1,4)
assert res==3,Exception('必须等于3') # 或:assert res==3,('必须等于3')
print('其他操作')
3.asser后面是true,才能执行下面的代码,否则直接报错,程序停止运行
4.类似于:
if not res==3:
raise Exception('不等于3')
print('其他操作')
drf之请求
回顾
1.已经了解到:
1.视图类:APIView
2.序列化组件:Serializer,ModelSerializer
3.drf:Request类的对象
4.drf:Response
2.REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。
3.REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典[QueryDict]对象保存到Request对象中。
4.Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。
5.无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。
Request类对象的常用属性
1.data:request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和 request.FILES属性,
提供如下特性:
1.包含了解析之后的文件和非文件数据
2.包含了对POST、PUT、PATCH请求方式解析后的数据
3.利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
2. .query_params
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。
3. 其他属性用起来和之前一样
请求,能够接受的编码格式
1.请求,能够接受的编码格式:urlencode、form-data、json
2.如何限制只能接受某种或几种编码格式
1.限制方式一:在视图类中写,但只是局部有效
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
parser_classes = [JSONParser,FormParser]
def get(self,request):
pass
...
2.限制方式二:在配置文件中写--->全局有效
在我们自己的项目中写:
# drf的配置,统一写成它
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
# 'rest_framework.parsers.FormParser',
# 'rest_framework.parsers.MultiPartParser'
],
}
ps:限制的编码是在:from rest_framework import settings中找到的
3.如果全局配置了只支持json,局部想支持3个怎么办
解决:只需要在局部,视图类中写三个即可
class BookView(APIView):
parser_classes = [JSONParser, FormParser,MultiPartParser]
pass
4.总结:能够处理的请求方式编码
-优先从视图类中找
-再去项目配置文件找
-再去drf默认的配置中找
drf之响应
响应类的对象Response
from rest_framework.response import Response
构造方式
1.return Response({code:100})
Response(data, status=None, template_name=None, headers=None, content_type=None)
data数据不要是render处理之后的数据,只需传递python的内建类型数据即可,REST framework会使用renderer渲染器处理data。
data不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用Serializer序列化器序列化处理后(转为了Python字典类型)再传递给data参数。
2.参数说明:
1.data: 响应提的内容,可以是字符串、字典、列表;
2.status: http响应状态码,默认200; # drf把所有响应码都定义成了一个常量
3.template_name: 模板名称,用浏览器访问,看到好看的页面,而用postman访问,返回正常数据; ps:网页打开,需要在应用里注册:rest_framework
4.headers: 用于存放响应头信息的字典;
ps:响应头加数据-->headers={'name':'nana'}
5.content_type: 响应编码,一般不用。响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
ps:data,status,headers
状态码
为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。
1.信息告知 - 1xx
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
2.成功 - 2xx
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
3.)重定向 - 3xx
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
4.客户端错误 - 4xx
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
5.服务器错误 - 5xx
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
响应格式
1.REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。
2.REST framework提供了Renderer渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。
3.默认的响应格式有两种:纯json、浏览器看到的样子
4.响应格式的限制方式
1.限制方式一:在视图类中写,但只是局部有效
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookView(APIView):
renderer_classes = [BrowsableAPIRenderer]
def get(self,request):
pass
...
2.限制方式二:在配置文件中写--->全局有效
在我们自己的项目中写:
# drf的配置,统一写成它
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}
ps:限制的编码是在:from rest_framework import settings中找到的
5.全局配置了只支持json,局部想支持2个
解决:只需要在局部,视图类中,写2个即可
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookView(APIView):
renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
常用属性
1.data
传给response对象的序列化后,但尚未render处理的数据
2.status_code
状态码的数字
3.content
经过render处理后的响应数据
视图之两个视图基类
1.APIView:是REST framework提供的所有视图的基类,继承自Django的View父类。
APIView:drf最顶层的视图类,继承了原生djagno的View
1 去除了csrf
2 包装了新的request
3 在执行视图类的方法之前,执行了三大认证
4 处理了全局异常
2.GenericAPIView:GenericAPIView继承了APIView
GenericAPIView
使用APIView+序列化类+Response写接口
from .serializer import BookSerialzier
from rest_framework.response import Response
from .models import Book
class BookView(APIView):
def get(self, request):
qs = Book.objects.all()
ser = BookSerialzier(qs, many=True)
return Response({'code': 100, 'msg': '成功', 'results': ser.data})
def post(self, request):
ser = BookSerialzier(data=request.data)
print(ser)
if ser.is_valid():
print(ser.validated_data)
ser.save()
return Response({'code': 100, 'msg': '成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.all().get(pk=pk)
ser = BookSerialzier(book)
return Response({'code': 100, 'msg': '成功', 'results': ser.data})
def put(self, request, pk):
book = Book.objects.get(pk=pk)
ser = BookSerialzier(data=request.data, instance=book)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '更新成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
使用GenericAPIView+序列化类+Response写接口
# GenericAPIView伪代码
class GenericAPIView(APIView):
queryset = None
serializer_class = None
def get_queryset(self):
return self.queryset
def get_serializer(self):
return self.serializer_class
def get_object(self):
return self.get_queryset().filter(pk=pk)
from rest_framework.generics import GenericAPIView
class BookView(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerialzier
def get(self, request):
qs = self.get_queryset()
ser = self.get_serializer(qs, many=True)
return Response({'code': 100, 'msg': '成功', 'results': ser.data})
def post(self, request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '成功'})
else:
print(ser.errors)
return Response({'code': 1001, 'msg': ser.errors})
class BookDetailView(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerialzier
def get(self, request, pk):
book = self.get_object()
ser = self.get_serializer(book)
return Response({'code': 100, 'msg': '成功', 'results': ser.data})
def put(self, request, pk):
book = self.get_object()
ser = self.get_serializer(data=request.data,instance = book)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '更新成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
类属性方法
类属性
1.queryset:要序列化的所有数据
2.serializer_class:序列化类
3.lookup_field = 'pk' :查询单条时的key值
4.filter_backends:过滤类
5.pagination_class:分页类
类方法
1.get_queryset():获取所有要序列化的数据【后期可以重写】
2.get_serializer : 返回序列化类【后期可以重写】
3.get_object :获取单个对象
总结
1.以后继承GenericAPIView写接口
1.必须配置类属性
queryset
serializer_class
2.想获取要序列化的所有数据
get_queryset()
3.想使用序列化类:
get_serializer
4.想拿单条
get_object
作业
1.原生django想往响应头加数据,如何加?
1.在视图函数或者中间件中创建一个HttpResponse对象,或者使用现有的HttpResponse对象。
2.使用HttpResponse对象的['key']属性,将需要添加的响应头的键和值作为字典项添加进去。
3.以下是一个示例代码,展示如何在Django中往响应头添加数据:
from django.http import HttpResponse
def my_view(request):
response = HttpResponse()
response['X-Custom-Header'] = 'Custom Value'
return response
2.编写一个post接口,只能接受json编码格式,响应json格式,响应头中加入:Access-Control-Allow-Origin = "*"
from rest_framework.views import APIView
from .serializer import BookSerialzier
from rest_framework.response import Response
from .models import Book
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
class BookView(APIView):
parser_classes = [JSONParser]
renderer_classes = [JSONRenderer]
def post(self, request):
ser = BookSerialzier(data=request.data)
print(ser)
if ser.is_valid():
print(ser.validated_data)
ser.save()
return Response({'code': 100, 'msg': '成功'},headers={'Access-Control-Allow-Origin':'*'})
else:
return Response({'code': 100, 'msg': ser.errors})
3、基于GenericAPIView编写图书5个接口,带出版社和作者
from django.shortcuts import render
# Create your views here.
from rest_framework.generics import GenericAPIView
from .models import Book
from .serializer import BookSerializer
from rest_framework.response import Response
class BookView(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self,request):
qs = self.get_queryset()
ser = self.get_serializer(qs,many = True)
return Response({'code':100,'msg':'查询成功','data':ser.data})
def post(self,request):
ser = self.get_serializer(data = request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '添加成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
class BookDetail(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self,request,pk):
qs = self.get_object()
ser = self.get_serializer(qs)
return Response({'code': 100, 'msg': '查询成功', 'data': ser.data})
def put(self,request,pk):
qs = self.get_object()
ser = self.get_serializer(data = request.data,instance = qs)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
def delete(self,request,pk):
self.get_object().delete()
return Response({'code': 100, 'msg': '删除成功'})
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['name','price','publish_name','author_list','authors','publish']
extra_kwargs = {
'authors':{'write_only':True},
'publish':{'write_only':True}
}
publish_name = serializers.SerializerMethodField(read_only=True)
author_list = serializers.ListField(read_only=True)
def get_publish_name(self,obj):
return obj.publish.name
4.封装5个类:ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,
class ListModelMixin(GenericAPIView):
def list(self):
qs = self.get_queryset()
ser = self.get_serializer(qs, many=True)
return Response({'code': 100, 'msg': '查询成功', 'data': ser.data})
class CreateModelMixin(GenericAPIView):
def create(self,request):
ser = self.get_serializer(data = request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '添加成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
class UpdateModelMixin(GenericAPIView):
def update(self,request):
qs = self.get_object()
ser = self.get_serializer(data=request.data, instance=qs)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
class RetrieveModelMixin(GenericAPIView):
def retrieve(self):
qs = self.get_object() #
print(qs)
ser = self.get_serializer(qs)
print(ser)
return Response({'code': 100, 'msg': '查询成功', 'data': ser.data})
class DestroyModelMixin(GenericAPIView):
def destroy(self):
self.get_object().delete()
return Response({'code': 100, 'msg': '删除成功'})
# Create your views here.
from rest_framework.generics import GenericAPIView
from .models import Book
from .serializer import BookSerializer
from rest_framework.response import Response
class BookView(ListModelMixin,CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self,request):
return self.list()
def post(self,request):
return self.create(request)
class BookDetail(UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self,request,pk):
return self.retrieve()
def put(self,request,pk):
return self.update(request)
def delete(self,request,pk):
return self.destroy()
别人写的
from rest_framework.generics import GenericAPIView
from .models import Book
from .serializer import BookSerializer
from rest_framework.mixins import RetrieveModelMixin,ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin
class BookView(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self,request):
return self.list(request)
def post(self,request):
return self.create(request)
class BookDetail(GenericAPIView,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self,request,pk):
return self.retrieve(request)
def put(self,request,pk):
return self.update(request)
def delete(self,request,pk):
return self.destroy(request)
4.基于DRF的Response,封装一个自己的Response,使它更符合我们规范{code:100,msg:成功,data:...}
from rest_framework.generics import GenericAPIView
from .models import Book
from .serializer import BookSerializer
# from rest_framework.response import Response
from rest_framework.response import Response as DrfResponse
class Response(DrfResponse):
# def __init__(self, code = 100,msg=None,data = None):
def __init__(self, data: dict, status=None, template_name=None, headers=None, content_type=None):
if data.get("code") is None:
data["code"] = 100
if data.get("msg") is None:
data["msg"] = "请求成功"
super().__init__(data, status, template_name, headers, content_type)
class BookView(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self,request):
qs = self.get_queryset()
ser = self.get_serializer(qs,many = True)
return Response({
"msg": '查询成功',
"data": ser.data
})
def post(self,request):
ser = self.get_serializer(data = request.data)
if ser.is_valid():
ser.save()
return Response({
"msg": '添加成功'
})
else:
return Response({'msg': ser.errors})
class BookDetail(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self,request,pk):
qs = self.get_object()
ser = self.get_serializer(qs)
# self.lookup_field
return Response({'msg': '查询成功', 'data': ser.data})
def put(self,request,pk):
qs = self.get_object()
ser = self.get_serializer(data = request.data,instance = qs)
if ser.is_valid():
ser.save()
return Response({'msg': '修改成功'})
else:
return Response({'code':1001,'msg': ser.errors})
def delete(self,request,pk):
self.get_object().delete()
return Response({'msg': '删除成功'})
5.自己封装出9个视图子类,能方便实现5个接口中某一个或多个
class ListModelMixin(GenericAPIView):
def list(self):
qs = self.get_queryset()
ser = self.get_serializer(qs, many=True)
return Response({'code': 100, 'msg': '查询成功', 'data': ser.data})
class CreateModelMixin(GenericAPIView):
def create(self,request):
ser = self.get_serializer(data = request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '添加成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
class UpdateModelMixin(GenericAPIView):
def update(self,request):
qs = self.get_object()
ser = self.get_serializer(data=request.data, instance=qs)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
class RetrieveModelMixin(GenericAPIView):
def retrieve(self):
qs = self.get_object() #
print(qs)
ser = self.get_serializer(qs)
print(ser)
return Response({'code': 100, 'msg': '查询成功', 'data': ser.data})
class DestroyModelMixin(GenericAPIView):
def destroy(self):
self.get_object().delete()
return Response({'code': 100, 'msg': '删除成功'})
from rest_framework.generics import GenericAPIView
class ListAPIView(ListModelMixin):
def get(self,request):
return self.list()
class CreateAPIView(CreateModelMixin):
def post(self, request):
return self.create(request)
class RetrieveAPIView(RetrieveModelMixin):
def get(self,request,pk):
return self.retrieve()
class UpdateAPIView(UpdateModelMixin):
def put(self,request,pk):
return self.update(request)
class DestroyAPIView(DestroyModelMixin):
def delete(self,request,pk):
return self.destroy()
class ListCreateAPIView(ListModelMixin,CreateModelMixin):
def get(self,request):
return self.list()
def post(self,request):
return self.create(request)
class RetrieveUpdateDestroyAPIView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
def get(self,request,pk):
return self.retrieve()
def put(self,request,pk):
return self.update(request)
def delete(self,request,pk):
return self.destroy()
class RetrieveDestroyAPIView(RetrieveModelMixin,DestroyModelMixin):
def get(self,request,pk):
return self.retrieve()
def delete(self,request,pk):
return self.destroy()
class RetrieveUpdateAPIView(RetrieveModelMixin,UpdateModelMixin):
def get(self,request,pk):
return self.retrieve()
def put(self,request,pk):
return self.update(request)
from django.shortcuts import render
from .models import Book
from .serializer import BookSerializer
from rest_framework.response import Response
class BookView(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookDetail(RetrieveUpdateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
6 、封装一个视图类,实现某个表的5个接口,使用方式如下(这个比较难)
class ListModelMixin(GenericAPIView):
def list(self):
qs = self.get_queryset()
ser = self.get_serializer(qs, many=True)
return Response({'code': 100, 'msg': '查询成功', 'data': ser.data})
class CreateModelMixin(GenericAPIView):
def create(self,request):
ser = self.get_serializer(data = request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '添加成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
class UpdateModelMixin(GenericAPIView):
def update(self,request):
qs = self.get_object()
ser = self.get_serializer(data=request.data, instance=qs)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功'})
else:
return Response({'code': 100, 'msg': ser.errors})
class RetrieveModelMixin(GenericAPIView):
def retrieve(self):
qs = self.get_object() #
print(qs)
ser = self.get_serializer(qs)
print(ser)
return Response({'code': 100, 'msg': '查询成功', 'data': ser.data})
class DestroyModelMixin(GenericAPIView):
def destroy(self):
self.get_object().delete()
return Response({'code': 100, 'msg': '删除成功'})
class ListCreateAPIView(ListModelMixin,CreateModelMixin):
def get(self,request):
return self.list()
def post(self,request):
return self.create(request)
class RetrieveUpdateDestroyAPIView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
def get(self,request,pk):
return self.retrieve()
def put(self,request,pk):
return self.update(request)
def delete(self,request,pk):
return self.destroy()
class ModelViewSet(ListCreateAPIView,RetrieveUpdateDestroyAPIView):
def get(self,request,**kwargs):
if not kwargs:
return self.list()
else:
print(11)
return self.retrieve()
def post(self,request):
return self.create(request)
def put(self, request, pk):
return self.update(request)
def delete(self, request, pk):
return self.destroy()
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.contrib import admin
from django.urls import path,include
from .views import BookView
urlpatterns = [
path('admin/', admin.site.urls),
path('books/<int:pk>/',BookView.as_view() ),
path('books/',BookView.as_view() )]
7.研究importlib,如何动态导入模块
1.在Python中,你可以使用importlib模块来实现动态导入模块。importlib提供了一组函数,可以在运行时动态导入模块,而不是在代码的开头进行静态导入。
2.下面是使用importlib动态导入模块的一般步骤:
2.1. 首先,你需要导入importlib模块:
import importlib
2.2. 接下来,可以使用import_module()函数来动态导入模块。该函数接受模块的名称作为参数,并返回一个表示该模块的对象。你可以将该对象分配给一个变量,以便在后续的代码中使用该模块:
module_name = 'my_module' # 模块的名称
module = importlib.import_module(module_name)
3.3.可以使用module变量来访问被导入模块中的函数、变量或类:
module.some_function()
module.some_variable
ps:1.import_module()函数可以接受一个完整的模块名称,例如'my_package.my_module',也可以只接受模块名称的一部分。如果你只提供了模块的一部分名称,那么Python将在导入过程中根据当前的搜索路径查找匹配的模块。
2.如果你需要重新加载已经导入的模块,可以使用reload()函数:
importlib.reload(module)
reload()函数会重新加载指定的模块,并返回重新加载后的模块对象。