quickstartgit
# 安裝 RESTful pip install djangorestframework
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
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
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"), ]
則獲取到的數據,相應字段將改成超連接:
# 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重構:
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)), ]