Django REST framework 初識

1、官網快速實例

quickstartgit

# 安裝 RESTful
pip install djangorestframework

2、序列化

models.pydjango

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.pyjson

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.pyapi

鋪墊:app

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 的 Serializeride

Publisher表(沒有一對多和多對多字段)post

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 的 ModelSerializerui

Book表(有一對多和多對多字段)url

備註說明:ModelSerializer繼承Serializer;若是一對多字段中有參數source,post提交數據時 --> 則須要重寫save中的create方法;除此以外,對於多對多字段,若是使用下面的方法請求(get)數據,將會獲得更直觀的數據,但這裏並無解決post、put請求操做。spa

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"),
]

則獲取到的數據,相應字段將改成超連接:

3、使用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"), ]

4、使用基於類的通用視圖

# 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"), ]

5、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"),
]

6、使用路由器

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)),
]
相關文章
相關標籤/搜索