使用restframework

https://www.cnblogs.com/GGGG-XXXX/articles/9568816.html

第一步: 安装

pip install djangorestframework
pip install markdown                     #  Markdown 支持可浏览的API  
pip install django-filter                  #  支持过滤

第二步: 注册rest_framework 在settings中的INSTALLEED_APPS

INSTALL_APPS = (
 ......,
 'rest_framework'      
)

第三步: 创建表,(models.py)

from django.db import models

# Create your models here.
__all__ = ["Book", "Publisher", "Author"]

CHOICES = ((1, "Python"), (2, "linux"), (3, "Go"))


class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="图书名字")
    category = models.IntegerField(choices=CHOICES)
    pub_time = models.DateField()

    publisher = models.ForeignKey(to="Publisher")
    authors = models.ManyToManyField(to="Author")

    def __str__(self):
        return self.title

    class Meta:
        db_table = "01-图书表"
        verbose_name_plural = db_table


class Publisher(models.Model):
    title = models.CharField(max_length=32)

    def __str__(self):
        return self.title

    class Meta:
        db_table = "02-出版社"
        verbose_name_plural = db_table


class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="作者的名字")

    def __str__(self):
        return self.name

    class Meta:
        db_table = "03-作者表"
        verbose_name_plural = db_table
models.py
from django.contrib import admin
from . import models

for table in models.__all__:
    admin.site.register(getattr(models, table))
admin.py

第四步: 创建序列化器, 在APP中创建serializers.py文件

from rest_framework import serializers
from .models import Book


# 理解该文件的内容,为需要传输转换为json的字段的内容

class PublisherSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField(max_length=32)


class AuthorSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(max_length=32)


class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, "Python"), (2, "Linux"), (3, "Go"))
    category = serializers.CharField(max_length=32, source="get_category_display", read_only=True)
    post_category = serializers.ChoiceField(choices=CHOICES, write_only=True)
    pub_time = serializers.DateField()

    publisher = PublisherSerializer(read_only=True)
    authors = AuthorSerializer(many=True, read_only=True)

    publisher_id = serializers.IntegerField(write_only=True)
    author_list = serializers.ListField(write_only=True)

    def create(self, validated_data):
        # 创建验证通过的字段
        book_obj = Book.objects.create(title=validated_data["title"], category=validated_data["post_category"],
                                       pub_time=validated_data["pub_time"], publisher_id=validated_data["publisher_id"])
        # 多对多关系的用add添加
        book_obj.authors.add(*validated_data["author_list"])
        return book_obj

    def update(self, instance, validated_data):
        # 有就更新, 没有就是默认的.
        instance.title = validated_data.get("title", instance.title)
        instance.category = validated_data.get("post_category", instance.category)
        instance.pub_time = validated_data.get("pub_time", instance.pub_time)
        instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id)
        # 多对多关系字段的更新
        if validated_data.get("author_list"):
            instance.authors.set(*validated_data["author_list"])
        # 注意要保存
        instance.save()
        return instance
View Code

第五步: 视图函数

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer


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

    def post(self, request):
        book_obj = request.data
        print(request.data)
        ser_obj = BookSerializer(data=book_obj)
        if ser_obj.is_valid():
            print(ser_obj.validated_data)
            ser_obj.save()
            return Response(ser_obj.validated_data)
        else:
            return Response(ser_obj.errors)


# 筛选某个字段
class BookEditView(APIView):
    def get(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        ser_obj = BookSerializer(book_obj)
        return Response(ser_obj.data)

    def patch(self, request, id):
        book_obj = Book.objects.filter(id=id).filter()
        ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.is_valid()
            return Response(ser_obj.validated_data)
        else:
            return Response(ser_obj.errors)
View Code

第六步: 设计url

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^booklist/$', views.BookInfo.as_view()),
    url(r'^booklist/id=(?P<id>\d+)', views.BookEditView.as_view())
]
View Code

 

 

restframework阶段总结

安装: 

  pip install djangorestframework

  settings 中注册rest_framework APP

序列化

  声明一个序列化器

    类比models

  视图

class BookView(APIView):
    def get(self, request):
        queryset = Book.objectsd.all()
        ser_obj = BookSerializer(quesyset, many=True)

反序列化

  声明序列化器

    注意我们的正序跟反序列化字段类型不统一

    read_only

    write_only

    require=False

    自定义create

    自定义update

  视图

class BookView(APIView):
    def post(self, request):
        ser_obj = BookSerializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        else:
            return Response(ser_obj.errors)
class BookEditView(APIView):
    def put(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        ser_obj = BookSerializer(book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj, validated_data)
        else:
            return Response(ser_obj.errors)

注意这两个的区别.

 

验证

  单个字段的验证

def validate_字段名称(self, value):
    # 处理我们的验证逻辑

  多个字段的验证

def validate(self, attrs):
    attrs 所有传过来的数据 {}
    字典里含有字段的名称: 值

  自定义验证

def my_validate(value):
    处理自己的验证逻辑

给我们的字段加属性
validators=[my_validate]

  验证通过返回传进来的值

  验证不通过 raise serialisers.ValidationError("错误信息")

ModelSerializer

  序列化

class BookSerializer(serializers.ModelSerialezer):
    class Meta:
        model = Book
        field = "__all__"
        # 让我们的外键关系字段编程read_only=True
        depth = 1

  反序列化

class BookSerializer(serializers.Moddelzer):
    class Meta:
        model = Book
        field = ["id", "name"]

  SerializerMethodField

    publisher_info = serializers.SerializseMethodField()

    def get_字段名称(self, obj):

      obj序列化的每个模型对象

      通过ORM操作拿到自己想要的数据结构

      return 想要的数据结构

  增加额外的参数

extra_kwargs = {"category": {"write_only": True},"publisher": {"write_only": True},
                        "authors":{"write_only": True},"title": {"validators": [my_validate]}}

 

视图

  APIView View区别

    APIView继承View

    重新封装了request对象, 用Request类封装

      旧的request _request

      request.data 所有的数据

      request.quesry_params GET

  封装的流程

    每个视图都要配置queryset serializer_class

querset = Book.objects.all()
serializer_class = BookSerializer()

    class GenericAPIView(APIView):

      def get_queryset(self):

        return self.queryset.all()

      def get_serializer(self, *args, **kwargs):

        return self.get_serialize(*args, **kwargs)

 

    写每个方法类

      class  ListModeMixin(object):

        def list(self, request):

          原来的get方法逻辑

          获取queryset self.get_queryset

          获取序列化器 self.get-serializers(...)

    -- 修改视图
      class BookAPIView(GenericAPIView, ListModelMixin):
        querset = Book.objects.all()
        serializer_class = BookSerializer

        def get(self, request):
          return self.list(request)
   -- 路由的传参
   -- 希望按照我们的指定的去分发
   -- ViewSetMixin 重写as_view() 可以传参了
   -- 合并视图 ModelViewSet

 

对之前的代码进行封装(views.py)

第一步: 导入ViewSetMixin和ModelViewSet模块

from rest_framework.viewsets import ViewSetMixin, ModelVsiewSet

  1,初步抽出

  2, 抽离出获取的操作

  3, 最终结果

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Student
from .serializers import StudentInfoSerializer
from rest_framework.viewsets import ViewSetMixin, ModelViewSet


class GenericAPIView(APIView):
    # 每个表通过继承这个类,实现获取不同的queryset对象, 和serializer_class
    queryset = None
    serializer_class = None

    def get_queryset(self):
        return self.queryset.all()

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)


class ListModelMixin(object):
    # get 方法
    def list(self, request):
        queryset = self.get_queryset()
        ser_obj = self.get_serializer(queryset, many=True)
        return Response(ser_obj.data)


class ListCreateModelMixin(GenericAPIView, ListModelMixin):
    pass


class StudentInfo(ListCreateModelMixin):
    # 获取该表的queryset对象, 和序列化对象
    queryset = Student.objects.all()
    serializer_class = StudentInfoSerializer

    def get(self, request):
        return self.list(request)
View Code

 

其余的都一样

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Student
from .serializers import StudentInfoSerializer
from rest_framework.viewsets import ViewSetMixin, ModelViewSet


class GenericAPIView(APIView):
    # 每个表通过继承这个类,实现获取不同的queryset对象, 和serializer_class
    queryset = None
    serializer_class = None

    def get_queryset(self):
        return self.queryset.all()

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)


class ListModelMixin(object):
    # get 方法
    def list(self, request):
        queryset = self.get_queryset()
        ser_obj = self.get_serializer(queryset, many=True)
        return Response(ser_obj.data)


class CreateModelMixin(object):
    # post 方法
    def create(self, request):
        queryset = request.data
        ser_obj = self.get_serializer(data=queryset)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        else:
            return Response(ser_obj.errors)


class RetrieveModelMixin(object):
    def retrieve(self, request, id):
        obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(obj)
        return Response(ser_obj.data)


class UpdateModelMixin(object):
    def update(self, request, id):
        obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(instance=obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        else:
            return Response(ser_obj.errors)


class ListCreateModelMixin(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyModelMixin(GenericAPIView, RetrieveModelMixin, UpdateModelMixin):
    pass


class StudentInfo(ListCreateModelMixin):
    # 获取该表的queryset对象, 和序列化对象
    queryset = Student.objects.all()
    serializer_class = StudentInfoSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)

    # def get(self, request):
    #     studentInfo = Student.objects.all()
    #     ser_stu = StudentInfoSerializer(studentInfo, many=True)
    #     return Response(ser_stu.data)

    # def post(self, request):
    #     studentInfo = request.data
    #     ser_obj = StudentInfoSerializer(data=studentInfo)
    #     if ser_obj.is_valid():
    #         ser_obj.save()
    #         return Response(ser_obj.validated_data)
    #     else:
    #         return Response(ser_obj.errors)


class StudentUpdate(RetrieveUpdateDestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentInfoSerializer

    def get(self, request, id):
        return self.retrieve(request, id)

    # def get(self, request, id):
    #     studentInfo = Student.objects.filter(id=id).first()
    #     ser_stu = StudentInfoSerializer(studentInfo)
    #     return Response(ser_stu.data)

    def patch(self, request, id):
        return self.update(request, id)

    # def patch(self, request, id):
    #     studentInfo = Student.objects.filter(id=id).first()
    #     ser_stu = StudentInfoSerializer(instance=studentInfo, data=request.data, partial=True)
    #     if ser_stu.is_valid():
    #         ser_stu.save()
    #         return Response(ser_stu.validated_data)
    #     else:
    #         return Response(ser_stu.errors)
View Code

 

使用restframework封装好的实现

url.py

from django.conf.urls import url
from django.contrib import admin
from app01 import my_view

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # url(r'^api-schoolinfo/$', my_view.StudentInfo.as_view()),
    # url(r'^api-schoolinfo/(?P<id>\d+)$', my_view.StudentUpdate.as_view()),
    url(r'^api-schoolinfo/$', my_view.StudentsInfoAPIView.as_view({"get": "list", "post": "create"})),
    url(r'^api-schoolinfo/(?P<pk>\d+)$$', my_view.StudentsInfoAPIView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),


]

serializers.py

class StudentsInfoAPIView(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentInfoSerializer

分析url设置对应的源码分析

ModelViewSet ---> GenericViewSet ---> ViewSetMixin

使用serializers.ModelSerializer

class BookSerializer(serializers.ModelSerializer):
    category_dis= serializers.SerializerMethodField(read_only=True)
    publisher_info = serializers.SerializerMethodField(read_only=True)
    author_info = serializers.SerializerMethodField(read_only=True)

    def get_author_info(self, obj):
        # 通过obj拿到authors
        # 构建想要的数据结构返回
        authors = obj.authors.all()
        ret = []
        for author in authors:
            ret.append({
                "id": author.id,
                "name": author.name
            })
        return ret


    def get_category_dis(self, obj):
        return obj.get_category_display()

    def get_publisher_info(self, obj):
        # 序列化的Book对象
        # 通过Book对象找到我们的publisher对象
        # 就可以拿到我们想要的字段
        # 拼接成自己想要的数据结构
        ret = {
            "id": obj.publisher.id,
            "title": obj.publisher.title
        }
        return ret

    class Meta:
        model = Book
        # fields = ["id", "title", "put_time"]
        fields = "__all__"
        # 让你这些外键关系的字段变成read_only = True
        # depth = 1
        extra_kwargs = {"category": {"write_only": True},"publisher": {"write_only": True},
                        "authors":{"write_only": True},"title": {"validators": [my_validate]}}
View Code

 

 

 https://www.cnblogs.com/GGGG-XXXX/articles/9675911.html

posted @ 2018-10-29 17:15  猴里吧唧  阅读(121)  评论(0)    收藏  举报