Django REST framework 初识

一、官网快速实例

quickstart

# 安装 RESTful
pip install djangorestframework

二、序列化

models.py

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="作者")
    age = models.IntegerField(verbose_name="年龄")
    def __str__(self):
        return self.name

class Publisher(models.Model):
    name = models.CharField(max_length=32, verbose_name="出版社")
    email = models.EmailField(verbose_name="邮箱")
    address = models.CharField(max_length=128, verbose_name="地址")
    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="书名")
    price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="价格")
    publish_date = models.DateField(verbose_name="出版日期")
    # 与Publish建立一对多的关系,外键字段一般建立在多的一方
    publisher = models.ForeignKey(to="Publisher", verbose_name="出版社")
    # 与Author表建立多对多的关系,ManyToManyField通常设置在正向查询多的那一边,自动创建第三张表
    authors = models.ManyToManyField(to="Author", verbose_name="作者")
    def __str__(self):
        return self.title
View Code

urls.py

from django.conf.urls import url
from appxx import views

urlpatterns = [
    url(r"^publishers/$", views.PublisherList.as_view()),
    url(r"^publishers/(\d+)$", views.PublisherDetail.as_view()),
    url(r"^books/$", views.BookList.as_view()),
    url(r"^books/(\d+)$", views.BookDetail.as_view()),
]

views.py

铺垫:

from django.shortcuts import HttpResponse
from django.views import View
from appxx import models
from django.forms.models import model_to_dict
from django.core import serializers


class PublisherList(View):
    def get(self, request):
        """取数据"""

        # 方式一:
        publisher_list = models.Publisher.objects.all().values("name", "email", "address")
        return HttpResponse(publisher_list)

        # 方式二:
        publisher_list = models.Publisher.objects.all()
        temp = []
        for obj in publisher_list:
            temp.append(model_to_dict(obj))
        return HttpResponse(temp)

        # 方式三:
        publisher_list = models.Publisher.objects.all()
        data = serializers.serialize("json", publisher_list)
        return HttpResponse(data)
  
    def get(self, request):
       pass
View Code

RESTful 的 Serializer

Publisher表(没有一对多和多对多字段)

from appxx import models
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers


class PublisherSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=32)
    email = serializers.EmailField()
    address = serializers.CharField(max_length=128)

    def create(self, validated_data):
        # 根据提供的验证过的数据创建并返回一个新的"Publisher"实例
        return models.Publisher.objects.create(**validated_data)

    def update(self, instance, validated_data):
        # 根据提供的验证过的数据更新并返回一个已经存在的"Publisher"实例
        instance.name = validated_data.get("name", instance.name)
        instance.email = validated_data.get("email", instance.email)
        instance.address = validated_data.get("address", instance.address)
        instance.save()
        return instance


class PublisherList(APIView):
    def get(self, request):
        publisher_list = models.Publisher.objects.all()
        s = PublisherSerializer(publisher_list, many=True)
        return Response(s.data)

    def post(self, request):
        s = PublisherSerializer(data=request.data)
        if s.is_valid():
            s.save()
            return Response(s.data)
        return Response(s.errors)


class PublisherDetail(APIView):
    def get(self, request, pk):
        publisher = models.Publisher.objects.filter(pk=pk).first()
        s = PublisherSerializer(publisher)
        return Response(s.data)

    def put(self, request, pk):
        publisher = models.Publisher.objects.filter(pk=pk).first()
        s = PublisherSerializer(publisher, data=request.data)
        if s.is_valid():
            s.save()
            return Response(s.data)
        return Response(s.errors)

    def delete(self, request, pk):
        models.Publisher.objects.filter(pk=pk).delete()
        return Response("删除成功")

RESTful 的 ModelSerializer

Book表(有一对多和多对多字段)

备注说明:ModelSerializer继承Serializer;如果一对多字段中有参数source,post提交数据时 --> 则需要重写save中的create方法;除此之外,对于多对多字段,如果使用下面的方法请求(get)数据,将会得到更直观的数据,但这里并没有解决post、put请求操作。

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"  # fields = ("title", "price", "publish_date", "publisher", "authors")

    # 一对多,通过source="本张表一对多字段.关联的表的任一字段",即可获取到对应的数据;如果不写,则获取到的是pk值
    publisher = serializers.CharField(source="publisher.name")

    # 多对多,通过source="本张表多对多字段.all",获取到的是 QuerySet 数据;如果不写,则获取到的是pk值
    # authors = serializers.CharField(source="authors.all")

    # 多对多,还可以用下面的方法获取到关联的数据
    # authors = serializers.SerializerMethodField()

    # def get_authors(self, obj):  # 格式:get_多对多字段名(self, obj)
    #     temp = []
    #     for author in obj.authors.all():
    #         temp.append(author.name)
    #     return temp

    # 重写save中的create方法
    def create(self, validated_data):
        obj = models.Book.objects.create(
            title=validated_data["title"],
            price=validated_data["price"],
            publish_date=validated_data["publish_date"],
            publisher_id=validated_data["publisher"]["name"],
        )
        obj.authors.add(*validated_data["authors"])
        return obj


class BookList(APIView):
    def get(self, request):  # 获取书籍列表
        book_list = models.Book.objects.all()
        s = BookSerializer(book_list, many=True)
        return Response(s.data)

    def post(self, request):  # 新增书籍
        s = BookSerializer(data=request.data)
        if s.is_valid():
            s.save()  # 实际执行的是create()方法
            return Response(s.data)
        return Response(s.errors)


class BookDetail(APIView):
    def get(self, request, pk):  # 获取某本书籍
        book = models.Book.objects.filter(pk=pk).first()
        s = BookSerializer(book)
        return Response(s.data)

    def put(self, request, pk):  # 修改某本书籍
        book = models.Book.objects.filter(pk=pk).first()
        s = BookSerializer(book, data=request.data)
        if s.is_valid():
            s.save()  # 实际执行的是update()方法
            return Response(s.data)
        return Response(s.errors)

    def delete(self, request, pk):  # 删除某本书籍
        models.Book.objects.filter(pk=pk).delete()
        return Response("删除成功")

超链接API:HyperlinkedModelSerializer(继承ModelSerializer)

官网内容

class BookSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"

    publisher = serializers.HyperlinkedIdentityField(
        view_name="publisher_detail",
        lookup_field="publisher_id",
        lookup_url_kwarg="pk"
    )


class BookList(APIView):
    def get(self, request):
        book_list = models.Book.objects.all()
        s = BookSerializer(book_list, many=True, context={"request": request})
        return Response(s.data)


class BookDetail(APIView):
    def get(self, request, pk):
        book = models.Book.objects.filter(pk=pk).first()
        s = BookSerializer(book, context={"request": request})
        return Response(s.data)

urls.py部分:

from django.conf.urls import url
from appxx import views

urlpatterns = [
    url(r"^publishers/$", views.PublisherList.as_view(), name="publisher_list"),
    url(r"^publishers/(?P<pk>\d+)/$", views.PublisherDetail.as_view(), name="publisher_detail"),
    url(r"^books/$", views.BookList.as_view(), name="book_list"),
    url(r"^books/(\d+)/$", views.BookDetail.as_view(), name="book_detail"),
]

则获取到的数据,相应字段将改为超链接:

三、使用mixins

# views.py
from
appxx import models from rest_framework import serializers from rest_framework import mixins from rest_framework import generics class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = "__all__" class BookList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializer 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 BookDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializer 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)
# urls.py
urlpatterns = [ url(r"^books/$", views.BookList.as_view(), name="book_list"), url(r"^books/(?P<pk>\d+)/$", views.BookDetail.as_view(), name="book_detail"), ]

四、使用基于类的通用视图

# views.py
from
appxx import models from rest_framework import serializers from rest_framework import generics class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = "__all__" class BookList(generics.ListCreateAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializer class BookDetail(generics.RetrieveUpdateDestroyAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializer
# urls.py
urlpatterns = [ url(r"^books/$", views.BookList.as_view(), name="book_list"), url(r"^books/(?P<pk>\d+)/$", views.BookDetail.as_view(), name="book_detail"), ]

五、ViewSet

使用ViewSet重构:

from appxx import models
from rest_framework import serializers
from rest_framework import viewsets


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"


class BookViewSet(viewsets.ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

将ViewSet明确绑定到URL:

from django.conf.urls import url
from appxx import views

urlpatterns = [
    url(r"^books/$", views.BookViewSet.as_view({
        "get": "list",
        "post": "create"}), name="book_list"),
    url(r"^books/(?P<pk>\d+)/$", views.BookViewSet.as_view({
        "get": "retrieve",
        "put": "update",
        "patch": "partial_update",
        "delete": "destroy"}), name="book_detail"),
]

将URL整理一下:

from django.conf.urls import url
from appxx import views

book_list = views.BookViewSet.as_view({
        "get": "list",
        "post": "create"})
book_detail = views.BookViewSet.as_view({
        "get": "retrieve",
        "put": "update",
        "patch": "partial_update",
        "delete": "destroy"})

urlpatterns = [
    url(r"^books/$", book_list, name="book_list"),
    url(r"^books/(?P<pk>\d+)/$", book_detail, name="book_detail"),
]

六、使用路由器

from django.conf.urls import url, include
from appxx import views
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r"books", views.BookViewSet)
router.register(r"publishers", views.PublisherViewSet)

urlpatterns = [
    url(r"", include(router.urls)),
]

 

posted @ 2018-12-28 11:28  就俗人一个  阅读(296)  评论(0编辑  收藏  举报