一、APIView基本使用
首先Drf是一个Django第三方的App 它只适用于Django 如果使用到别的框架是使用不了的 安装Drf之后就可以导入一个视图累APIView 所以要使用Drf写视图类 都要继承APIView以及其子类 在安装完Drf(DjangoRestFrameWork)它会默认把系统的Django版本更新到最新 这个时候运行会报错 只要把Drf或者Django版本降低即可
首先展示使用View展示接口
path('movies/', MovieView.as_view())
class Movie(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
director = models.CharField(max_length=32)
class MovieView(View):
def get(self, request):
movie_list = Movie.objects.all()
res_list = []
for movie in movie_list:
res_list.append({'name': movie.name, 'price': movie.price, 'director': movie.director})
return JsonResponse(res_list, safe=False, json_dumps_params={'ensure_ascii': False})
'''
JsonResponse只能序列化字典以及列表 safe如果是True会抛出异常
json_dumps_params={'ensure_ascii': False}把数据转换成中文
movie_list是一个queryset对象不能直接序列化 只能通过for循环一个一个拼成列表套字典形式
'''
访问结果:[{"name": "今天你做了嘛?", "price": "999", "director": "Mr.Mei"},
{"name": "我也想做!", "price": "666", "director": "Mr.Jin"}]
使用APIView+Response展示接口
from rest_framework.views import APIView
from rest_framework.response import Response
class MovieView(APIView):
def get(self, request):
print(request._request)
print(type(request._request))
movie_list = Movie.objects.all()
res_list = []
for movie in movie_list:
res_list.append({'name': movie.name, 'price': movie.price, 'director': movie.director})
return Response(res_list)
'''
注意一定到在Settings里面注册Drf这个app 如果不注册用浏览器访问会报错
如果注册了使用浏览器浏览就会看到一个被美化的界面 不仅仅是Json格式的数据
'''
二、APIView源码分析
首先入口APIView
class MovieView(APIView):
@classmethod
def as_view(cls, **initkwargs):
view = super().as_view(**initkwargs)
return csrf_exempt(view)
所以请求来了路由匹配成功会执行View类里面的as_view类方法内的View闭包函数实际上还是view的as_view没有csrf验证
def view(request, *args, **kwargs):
return self.dispatch(request, *args, **kwargs)
def dispatch(self, request, *args, **kwargs):
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers
try:
self.initial(request, *args, **kwargs)
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
1 只要继承APIView都没有csrf的认证了
2 以后视图类中使用的request对象,已经变成了drf提供的Request类的对象了
3 执行视图类的方法之前,执行了3大认证(认证,权限,频率)
4 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理
三、Request类源码分析
-原生djagno 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest
-drf的request是这个类的对象:rest_framework.request.Request
-用起来,像之前一样
print(request.method)
print(request.path)
print(request.GET)
print(request.POST)
-类中有个魔法方法:__getattr__ 对象.属性,属性不存在会触发它的执行
def __getattr__(self, attr):
try:
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
-以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的)
-新的request内部有个老的request 就是 request._request
-data 是个方法,被property装饰了,变成了数据属性用
-以后body体中提交的数据,都从这里取(request.POST)
-urlencoded,form-data:提交的数据在request.POST中
-json格式提交的数据,在requets.POST中没有 它在request.body中
-现在无论那种格式,都从request.data中取
-query_params:get请求提交的参数 等同于request._request.GET 或 request.GET
-其他:取文件也是从request.FILES中取 跟之前一样
验证 原生requets.POST 只有urlencoded和form-data格式提交的数据 json格式提交的数据在body中
拿出来自己处理 但是drf的request中有个data data中可以取到任意编码提交的数据
request.data 有时候是(urlencoded,form-data)QueryDict 有时候(json)是字典
1 在类中只要以__开头 __结尾的都称之为魔法方法
2 这种方法不需要手动调用,某种情况会自动触发
3 讲过的: __init__,__str__,__call__,......
四、序列化组件介绍
咱在写电影接口的时候涉及到一个问题 要把Queryset单个Movie对象转换成Json格式字符串给前端这个过程就叫做序列化 要是我们现在只要电影名以及导演呢?(就得去删除或者添加)于是Drf就给我们提供了一种可以快速实现序列化的类就跟Forms很像了
基于APIView+Response+序列化类写接口
创建一个文件 serializer.py
from rest_framework.serializers import Serializer
from rest_framework import serializers
class MovieSerializers(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
director = serializers.CharField()
views
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import MovieSerializers
class MovieView(APIView):
def get(self, request):
movie_list = Movie.objects.all()
ser = MovieSerializers(instance=movie_list, many=True)
return Response(ser.data)
'''这个时候我们如果需要添加一条数据在类里面添加字段即可 如果想不要删除掉即可 这就非常的方便'''
五、序列化组件基本使用
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('movies/', MovieView.as_view()),
path('movies/<int:pk>/', MovieDetailView.as_view()),
]
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import MovieSerializers
class MovieView(APIView):
def get(self, request):
movie_list = Movie.objects.all()
ser = MovieSerializers(instance=movie_list, many=True)
return Response(ser.data)
class MovieDetailView(APIView):
def get(self, request, pk):
movie = Movie.objects.filter(pk=pk).first()
ser = MovieSerializers(instance=movie)
return Response(ser.data)
'''
获取单条与获取多条的方式都是Get 但是如果多条与单条一起使用混合度比较高 所以单独重写一个获取单条的类
我们发送Get请求单条数据都会跟上ID号所以基本格式是这样 http://127.0.0.1:8000/movies/1/ 所以要在类中添加到ID才能获取到哪一条数据
'''
六、反序列化基本使用
序列化就是查询多个以及查询单个 但是反序列化就是新增和修改了 删除直接删除即可不涉及到序列化
新增
class MovieView(APIView):
def get(self, request):
movie_list = Movie.objects.all()
ser = MovieSerializers(instance=movie_list, many=True)
return Response(ser.data)
def post(self, request):
ser = MovieSerializers(data=request.data)
if ser.is_valid():
ser.save()
''' 这个时候发送post请求会发生报错 NotImplementedError: `create()` must be implemented.
这个时候点击我们点击save查看源码是调用了Save会触发BaseSerializer的方法
判断了 如果instance有值执行update,没有值执行create 看到create没有写 所以我们得重写Create'''
return Response(ser.data)
else:
return Response(ser.errors)
'''重写create方法'''
class MovieSerializers(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
director = serializers.CharField()
def create(self, validated_data):
res = Movie.objects.create(**validated_data)
return res
修改
class MovieDetailView(APIView):
def get(self, request, pk):
movie = Movie.objects.filter(pk=pk).first()
ser = MovieSerializers(instance=movie)
return Response(ser.data)
def put(self, request, pk):
movie = Movie.objects.filter(pk=pk).first()
ser = MovieSerializers(instance=movie, data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
def update(self, instance, validated_data):
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.director = validated_data.get('director')
instance.save()
return instance
删除
def delete(self, request, pk):
Movie.objects.filter(pk=pk).delete()
return Response()
技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点点赞收藏+关注 谢谢支持 !!!
|