drf 代码流程总结

一、基于APIView+Response写五个接口

view.py

from django.shortcuts import render
from rest_framework.views import APIView
from .serializer import BookSerializer, PublishSerializer
# Create your views here.
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Book, Publish


class BookView(APIView):
    # 查询所有信息
    def get(self, request):
        book_list = Book.objects.all()
        ser = BookSerializer(instance=book_list, 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 BookDetailView(APIView):
    # 查询单条信息
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(ser.data)

    # 修改信息
    def put(self, request, pk):
        book = Book.objects.filter(pk=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 delete(self,request,pk):
        Book.objects.filter(pk=pk).first()
        return Response()

models.py

from django.db import models

# Create your models here.
from rest_framework.views import APIView


class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)


class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)

serializer.py

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

    # 重写create方法
    def create(self, validated_data):
        res = Book.objects.create(**validated_data)
        return res

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish = validated_data.get('publish')
        instance.save()
        return instance


class PublishSerializer(serializers.Serializer):
    name = serializers.CharField()
    city = serializers.CharField()

urls.py

    path('books/',views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view())

二、序列化类高级用法之定制序列化字段

第一种实现

models.py

from django.db import models

# Create your models here.
from django.db import models


class Book(models.Model):
    name = models.CharField(max_length=32,verbose_name='书本姓名')
    price = models.DecimalField(max_digits=5, decimal_places=2,verbose_name='价格')
    publish_date = models.DateField(null=True,verbose_name='出版日期')

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    def __str__(self):
        return self.name

    # 写了个方法,可以包装成数据属性,也可以不包
    def publish_de(self):
        return {'name': self.publish.name, 'city': self.publish.city, 'email': self.publish.email}

    def author_li(self):
        res_list = []
        for author in self.authors.all():
            res_list.append({'id': author.id, 'name': author.name, 'age': author.age})
        return res_list


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

admin.py

from django.contrib import admin
from .models import *

# Register your models here.
admin.site.register(Book)
admin.site.register(Author)
admin.site.register(AuthorDetail)
admin.site.register(Publish)

views.py

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
from .models import Book


# Create your views here.
class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        ser = BookSerializer(instance=book_list, many=True)
        return Response(ser.data)

serializer.py

from rest_framework import serializers


class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=32, min_length=3)
    price = serializers.IntegerField(max_value=32, min_value=6)
    publish_date = serializers.DateField()
    publish = serializers.SerializerMethodField()

    def get_publish(self, obj):
        return {'name': obj.publish.name, 'city': obj.publish.city, 'email': obj.publish.email}

2.  在表模型中写

models.py中

# 表模型中
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField(null=True)
 
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')
 
    # 写了个方法,可以包装成数据属性,也可以不包
    def publish_detail(self):
        return {'name': self.publish.name, 'city': self.publish.city, 'email': self.publish.email}
 
    def author_list(self):
        res_list = []
        for author in self.authors.all():
            res_list.append({'id': author.id, 'name': author.name, 'age': author.age})
        return res_list
    
# 序列化类中
class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8, min_length=3)
    price = serializers.IntegerField(min_value=10, max_value=99)
    publish_date = serializers.DateField()
 
    # 方式二:在表模型中写方法
    publish_detail = serializers.DictField(read_only=True)
    # 练习,使用方式二实现,显示所有作者
    author_list = serializers.ListField(read_only=True)

反序列化之数据校验

##### 反序列化字段校验
from rest_framework.exceptions import ValidationError
 
 
class BookModelSerializer(serializers.ModelSerializer):
    name=serializers.CharField(max_length=8,min_length=3)
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_date', 'publish', 'authors', 'publish_de', 'author_li']  # 列表中有什么,就是序列化哪个字段
        extra_kwargs = {
            'name': {'max_length': 80, 'min_length': 3, 'error_messages': {'min_length': "太短了"}},
            'price': {'max_value': 100, 'min_value': 9},
            'publish': {'write_only': True},
            'authors': {'write_only': True},
        }
 
    # 给name字段加局部钩子,一定不要写在内部类中
    def validate_name(self, name):
        if name.startswith('sb'):
            # 校验不通过,抛异常
            raise ValidationError('不能以sb卡头')
        else:
            return name
 
    def validate_price(self, price):
        if price == 44:
            raise ValidationError('不能是44,没有为什么')
        else:
            return price
 
    def validate(self, attrs):
        if attrs.get('name') == attrs.get('publish_date'):
            raise ValidationError('名字不能等于日期')
        else:
            return attrs

 使用GenericAPIView写出book的5个接口

 
from rest_framework.generics import GenericAPIView
 
 
class BookView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
 
    def get(self, request):
        book_list = self.get_queryset()
        ser = self.get_serializer(instance=book_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({'code': 100, 'msg': "新增成功"}, status=201)
        else:
            return Response({'code': 101, 'msg': ser.errors})
 
 
class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
 
    def get(self, request, pk):
        book = self.get_object()
        ser = self.get_serializer(instance=book)
        return Response(ser.data)
 
    def put(self, request, pk):
        book = self.get_object()
        ser = self.get_serializer(instance=book,data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':100,'msg':"修改成功"},status=201)
        else:
            return Response({'code':101,'msg':ser.errors})
 
    def delete(self,request,pk):
        self.get_queryset().filter(pk=pk).delete()
        return Response('')

五个扩展类

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \
    ListModelMixin


class UserView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class UserDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)
    
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

九个视图子类

from rest_framework.generics import ListAPIView, CreateAPIView, RetrieveAPIView, DestroyAPIView, UpdateAPIView
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveUpdateAPIView, \
    RetrieveDestroyAPIView


class UserView(ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetailView(RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

视图集

视图类
from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
class UserView(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
路由
path('user/', views.UserView.as_view({'get': 'list', 'post': 'create'})),
path('user/<int:pk>', views.UserView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),

自动生成路由

from django.contrib import admin
from django.urls import path, include   # include是干分发路由用的
from app01 import views
 
# 自动生成路由
# drf提供了两个路由类,以后继承了ViewSetMixin及其子类的视图类,就可以使用这两个路由类来自动生成路由,(也就是不用自己写了,让他自动去生成路由)
# 使用步骤
# 第一步:导入路由类
from rest_framework.routers import SimpleRouter, DefaultRouter
 
# 第二步:实例化得到对象
router = SimpleRouter()
# router = DefaultRouter()  就多一个根路径,和SimpleRouter几乎没差别,平时用的还是SimpleRouter多一些
# 第三步:注册路由(可以注册多个)
# 注册需要传三个参数  {第一个参数:路径 第二个参数:视图类(继承了ViewSetMixin及其子类的视图类) 第三个参数:别名,可以不写(默认以路径作为别名)}
router.register('books', views.BookView, 'books')
router.register('publish', views.PublishView, 'publish')
 
router.register('user', views.UserView, 'user')
 
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
    # path('user/', views.UserView.as_view({'get':'login'})),
    # path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
    # path('books/<int:pk>', views.BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
 
# 第四步:把自动生成的路由添加到urlpatterns中
# 方式一:
# urlpatterns+=router.urls
 
# 方式二,使用include添加   
# path('', include(router.urls)),

 

posted @ 2022-10-14 20:57  W-Y-N  阅读(85)  评论(0)    收藏  举报