1 兩個視圖基類 # APIView >之前一直在用 》drf提供的最頂層的父類 》以後所有視圖類,都繼承自它 # GenericAPIView--》繼承自APIView--》封裝 1.1 繼承APIView+序列化類+Response寫介面 urls.py--子路由--app01--urls.py ...
1 兩個視圖基類
# APIView--->之前一直在用---》drf提供的最頂層的父類---》以後所有視圖類,都繼承自它
# GenericAPIView--》繼承自APIView--》封裝
1.1 繼承APIView+序列化類+Response寫介面
urls.py--子路由--app01--urls.py
from django.contrib import admin
from django.urls import path,include
from app01 import views
urlpatterns = [
path('books/',views.BookView.as_view()),
path('books/<int:pk>/',views.BookDetaiView.as_view())
]
序列化類
serializer.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model=Book
# 'publish', 'authors'反序列化
fields=['id','name','price','publish','authors','author_list','publish_detail']
extra_kwars={
'publish':{'weite_only':True},
'authors':{'weite_only':True},
'author_list':{'read_only':True},
'publish_detail':{'read_only':True},
}
表模型
from django.db import models
# Create your models here.
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
@property
def publish_detail(self):
return {'name': self.publish.name, 'city': self.publish.city}
@property
def author_list(self):
l = []
for author in self.authors.all():
l.append({'name': author.name, 'age': author.age})
return l
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
def __str__(self):
return self.name
class AuthorDetail(models.Model):
telephone = models.BigIntegerField()
birthday = models.DateField()
addr = models.CharField(max_length=64)
class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
def __str__(self):
return self.name
class Meta:
verbose_name = '出版社'
verbose_name_plural = verbose_name
視圖類
from .serializer import BookSerializer
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from .models import Book
from rest_framework.response import Response
class BookView(APIView):
def get(self, request):
booklist = Book.objects.all()
ser = BookSerializer(instance=booklist, many=True)
return Response(ser.data)
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
class BookDetaiView(APIView):
def put(self, request, *args, **kwargs):
book = Book.objects.filter(pk=kwargs.get('pk')).first()
ser = BookSerializer(instance=book, data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
def get(self, request, *args, **kwargs):
book = Book.objects.filter(pk=kwargs.get('pk')).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
def delete(self, request, *args, **kwargs):
Book.objects.filter(pk=kwargs.get('pk')).first()
return Response('')
1.2 繼承GenericAPIView+序列化類+Response寫介面
#第二層繼承GenericAPIView+序列化類+Response寫介面
from rest_framework.generics import GenericAPIView
class BookView(GenericAPIView):
# 先配置兩個類屬性
#用的話必須寫
queryset =Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
object_list = self.get_queryset()#獲取所有要序列化的數據
ser = self.get_serializer(instance=object_list, many=True)#獲取序列化類
return Response(ser.data)
def post(self, request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
class BookDetaiView(GenericAPIView):
# 先配置兩個類屬性
queryset = Book.objects.all()
serializer_class = BookSerializer
def put(self, request, *args, **kwargs):
# book = Book.objects.filter(pk=kwargs.get('pk')).first()
obj=self.get_object()#獲取單條數據--》內部就是按pk從request中獲取,取除pk對應的值,查詢
ser = self.get_serializer(instance=obj, data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
def get(self, request, *args, **kwargs):
# book = Book.objects.filter(pk=kwargs.get('pk')).first()
obj=self.get_object()
ser = self.get_serializer(instance=obj)
return Response(ser.data)
def delete(self, request, *args, **kwargs):
# Book.objects.filter(pk=kwargs.get('pk')).first()
self.get_object().delete()
return Response('')
快速實現publish的5個介面
只需要修改視圖類上的兩個類屬性即可,其他的不用動
urls.py
from django.contrib import admin
from django.urls import path,include
from app01 import views
urlpatterns = [
#path('books/',views.BookView.as_view()),
#path('books/<int:pk>/',views.BookDetaiView.as_view()),
path('publish/',views.PublishView.as_view()),
path('publish/<int:pk>/',views.PublishDetaiView.as_view())
]
views.py
#快速實現publish的5個介面
from .models import Publish
from .serializer import PublishSerializer
class PublishView(GenericAPIView):
# 先配置兩個類屬性
#用的話必須寫
queryset =Publish.objects.all()
serializer_class = PublishSerializer
def get(self, request):
# object_list = self.queryset.all() # 獲取所有要序列化的數據
# #1 寫成方法的目的--》調用all()
# #2 子類可以重寫這個方法--》返回什麼,待序列化的數據就是什麼
# object_list = self.get_queryset() # 獲取所有要序列化的數據
object_list = self.get_queryset()#獲取所有要序列化的數據
ser = self.get_serializer(instance=object_list, many=True)#獲取序列化類
# 本質就是---》 self.serializer_class(instance=object_list, many=True)
return Response(ser.data)
def post(self, request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
class PublishDetaiView(GenericAPIView):
# 先配置兩個類屬性
queryset = Publish.objects.all()
serializer_class = PublishSerializer
def put(self, request, *args, **kwargs):
# book = Book.objects.filter(pk=kwargs.get('pk')).first()
obj=self.get_object()#獲取單條數據--》內部就是按pk從request中獲取,取除pk對應的值,查詢
ser = self.get_serializer(instance=obj, data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
def get(self, request, *args, **kwargs):
# book = Book.objects.filter(pk=kwargs.get('pk')).first()
obj=self.get_object()
ser = self.get_serializer(instance=obj)
return Response(ser.data)
def delete(self, request, *args, **kwargs):
# Book.objects.filter(pk=kwargs.get('pk')).first()
self.get_object().delete()
return Response('')
serializer.py
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = "__all__"
繼承GenericAPIView的寫法
-1 在類中,寫兩個類屬性:所有數據,序列化類
queryset = Book.objects.all()
serializer_class = BookSerializer
-2 獲取所有要序列化的數據
self.get_queryset()
-3 獲取序列化類
self.get_serializer(參數跟之前一樣)
-4 獲取單挑
self.get_object()
GenericAPIView源碼分析
-1 繼承了APIView
-2 有些類屬性--》目前只記住兩個queryset,serializer_class
queryset # 要序列化的所有數據
serializer_class # 序列化類
lookup_field = 'pk' # 查詢單條,前端傳入的參數對應值【pk】,轉換器
filter_backends # 後續要學的,過濾
pagination_class # 後續要學的,分頁
-3 有些對象方法
-get_queryset: 返回待序列化的數據
1 調用 .all
2 在子類中重寫,控制要序列化的數據
-get_serializer: 返回 序列化類 以後用它
-本質就是---》 self.serializer_class(instance=object_list, many=True)
-內部調用了:self.get_serializer_class
-後期在子類中重寫get_serializer_class,返回什麼序列化類,以後就以哪個序列化類做序列化
- get_serializer_class 它是用來重寫的
def get_serializer_class(self):
if self.request.method=='GET':
return '序列化的類'
else:
return '反序列化的類'
-get_object 獲取單條---》根據它:lookup_field 獲取
第三層:繼承 GenericAPIView+5個視圖擴展類+序列化類+Response
5個視圖擴展類(不是視圖類--》沒有繼承APIView及其子類,不能單獨用,需要配合GenericAPIView)---》每個分別寫的5個介面中得某一個方法
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, \
DestroyModelMixin
#CreateModelMixin 新增
#ListModelMixin 查詢所有
#RetrieveModelMixin 查詢單條
#UpdateModelMixin 修改
# DestroyModelMixin 銷毀
views.py
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, \
DestroyModelMixin
class BookView(GenericAPIView,CreateModelMixin,ListModelMixin):
# 先配置兩個類屬性
#用的話必須寫
queryset =Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
# object_list = self.get_queryset()#獲取所有要序列化的數據
# ser = self.get_serializer(instance=object_list, many=True)#獲取序列化類
# return Response(ser.data)
return super().list(request)
def post(self, request):
# 做保存,加了這一句---》目的是:子類可以重寫,增強擴展性
# self.perform_create(serializer)
return super().list(request)
class BookDetailView(GenericAPIView, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def put(self, request, *args, **kwargs):
return super().update(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
return super().retrieve(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return super().destroy(request, *args, **kwargs)
9個視圖子類
第四層:9個視圖子類---》視圖類
#CreateModelMixin 新增
#ListModelMixin 查詢所有
# ListCreateAPIView 新增+查詢所有
#RetrieveModelMixin 查詢單條
#UpdateModelMixin 修改
# DestroyModelMixin 銷毀
# RetrieveUpdateDestroyAPIView 查詢單條+修改+銷毀
# RetrieveDestroyAPIView 查詢單條+ 銷毀
# RetrieveUpdateAPIView查詢單條+修改
# CreateAPIView繼承了 GenericAPIView, CreateModelMixin,寫了post方法
from rest_framework.generics import CreateAPIView,ListAPIView,ListCreateAPIView
from rest_framework.generics import RetrieveAPIView,DestroyAPIView,UpdateAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.generics import RetrieveDestroyAPIView,RetrieveUpdateAPIView
#實現
class BookView(ListCreateAPIView):
# 先配置兩個類屬性
#用的話必須寫
queryset =Book.objects.all()
serializer_class = BookSerializer
class BookDetailView(RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# 實現新增,查所有和查詢一條
# class BookView(ListCreateAPIView):
# # 配置兩個類屬性
# queryset = Book.objects.all()
# serializer_class = BookSerializer
#
#
# class BookDetailView(RetrieveAPIView):
# queryset = Book.objects.all()
# serializer_class = BookSerializer