国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

10-django——RESTful API 之序列化

Bowman_han / 2476人閱讀

摘要:之序列化前后端分離就是前臺的開發和后臺的開發分離,這個技術方案的實現需要借助,簡單來說就是開發人員提供編程的接口被其他人調用,調用之后會返回數據供其使用安裝什么是序列化把模型對象轉換為格式然后響應出去,便于客戶端進行數據解析創建序列化類在應

Django RESTful API之序列化

前后端分離:就是前臺的開發和后臺的開發分離,這個技術方案的實現需要借助API,簡單來說就是開發人員提供編程的接口被其他人調用,調用之后會返回數據供其使用

安裝pip install djangorestframework

什么是序列化?:把模型對象轉換為JSON格式然后響應出去,便于客戶端進行數據解析

創建序列化類

在應用目錄下創建名為serializers.py的文件

from rest_framework import serializers
from myApp.models import Student, Grade
#給學生類創建序列化類
class StudentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = ("id", "name", "sex", "age", "content", "isDelete", "grade")
#該班級創建序列化類
class GradeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Grade
        fields = ("id", "name", "boyNum", "girlNum", "isDelete")
使用系列化

進入shell環境:python manage.py shell

引入序列化類,創建序列化對象查看可序列化的字段:

>>> from myApp.serializers import StudentSerializer
>>> serializer = StudentSerializer()
>>> print(serializer)
StudentSerializer():
    id = IntegerField(label="ID", read_only=True)
    name = CharField(max_length=20)
    sex = BooleanField(required=False)
    age = IntegerField(max_value=2147483647, min_value=-2147483648)
    contend = CharField(max_length=40)
    isDelete = BooleanField(label="IsDelete", required=False)
    grade = PrimaryKeyRelatedField(queryset=Grade.objects.all())

找到一個學生:

>>> from myApp.models import Student
>>> stu = Student.objects.get(pk=1)
>>> print(stu)
薛延美

依據學生創建序列化對象,再對對象進行序列化操作:

>>> serializer = StudentSerializer(stu)
>>> print(serializer.data)
{"id": 1, "name": "薛延美", "sex": False, "age": 20, "contend": "我叫薛延美", "isDelete": False, "grade": 4}
>>> print(type(serializer.data))

將數據渲染成JSON格式

>>> from rest_framework.renderers import JSONRenderer
>>> content = JSONRenderer().render(serializer.data)
>>> print(content)
b"{"id":1,"name":"xe8x96x9bxe5xbbxb6xe7xbex8e","sex":false,"age":20,"contend":"xe6x88
x91xe5x8fxabxe8x96x9bxe5xbbxb6xe7xbex8e","isDelete":false,"grade":4}"

反序列化:當客戶需要修改、增加、刪除數據時,就要這個過程反過來,就叫反序列化

>>> from rest_framework.parsers import JSONParser
>>> from django.utils.six import BytesIO
>>> stream = BytesIO(content)
>>> print(stream)
<_io.BytesIO object at 0x000001EECF597E08>
>>> stu2 = JSONParser().parse(stream)
>>> print(stu2)
{"id": 1, "name": "薛延美", "sex": False, "age": 20, "contend": "我叫薛延美", "isDelete": False, "grade": 4}
>>> print(type(stu2))

檢測數據并保存

>>> stu2.save()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: "dict" object has no attribute "save"
>>> serializer = StudentSerializer(data=stu2)
>>> print(serializer.is_valid())
True
>>> print(serializer.validated_data)
OrderedDict([("name", "薛延美"), ("sex", False), ("age", 20), ("contend", "我叫薛延美"), ("isDel
ete", False), ("grade", )])
>>> print(type(serializer.validated_data))

>>> print(serializer.validated_data["name"])
薛延美
>>> serializer.save()
視圖實現使用序列化
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse

from myApp.models import Student, Grade

from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from django.utils.six import BytesIO

from myApp.serializers import StudentSerializer, GradeSerializer

def studentsList(request):
    if request.method == "GET":
        stus = Student.objects.all()
        #序列化
        serializer = StudentSerializer(stus, many=True)
        return JsonResponse(serializer.data, safe=False)
    elif request.method == "POST":
        # content = JSONRenderer().render(request.POST)
        # stream = BytesIO(content)
        # stuDict = JSONParser().parse(stream)
        # serializer = StudentSerializer(data=stuDict)
        serializer = StudentSerializer(data=request.POST)
        if serializer.is_valid():
            #存數據
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse({"error":serializer.errors}, status=400)
def studentDetail(request, pk):
    try:
        stu = Student.objects.get(pk=pk)
    except Student.DoesNotExist as e:
        return JsonResponse({"error":str(e)}, status=404)

    if request.method == "GET":
        serializer = StudentSerializer(stu)
        return JsonResponse(serializer.data)
    elif request.method == "PUT":
        #content = JSONRenderer().render(request.data)
        #stream = BytesIO(content)
        #stuDict = JSONParser().parse(stream)
        # print(stuDict)
        #修改
        serializer = StudentSerializer(stu, data=request.data)
        if serializer.is_valid():
            #存數據
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse({"error":serializer.errors}, status=400)
    elif request.method == "DELETE":
        stu.delete()
        return HttpResponse(status=204,content_type="application/json")
Django RESTful API 之請求與響應 激活應用
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "myApp",
    "rest_framework",
]
Request對象
request.POST: 只能處理表單數據,并且只能處理POST請求

擴展: request.data 能處理各種請求的數據,可以處理PUT和PATCH請求的數據

Response對象
HttpResponse、JsonResponse類: 用于返回json數據,在return的時候需要指明json格式

擴展: Reponse類 會根據客戶端的請求頭信息返回正確的內容類型

狀態碼
發送http請求會返回各種各樣的狀態碼,但是狀態碼都是數字,不能夠明確的讓程序員了解是什么問題

擴展 HTTP_400_BAD_REQUEST 極大提高了可讀性

視圖

@api_view: 是裝飾器,用在基于函數的視圖上

APIView: 是類,用在基于類的視圖上

作用: 提供一些功能,讓程序員省去了很多工作,確保在視圖中收到request對象或在對象中添加上下文 裝飾器可以在接收到輸入錯誤的request.data時拋出ParseError異常,在適當的時候返回405狀態碼

代碼
# from django.shortcuts import render
# from django.http import HttpResponse, JsonResponse
from myApp.models import Student, Grade

# from rest_framework.renderers import JSONRenderer
# from rest_framework.parsers import JSONParser
# from django.utils.six import BytesIO

from myApp.serializers import StudentSerializer

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(["GET", "POST"])
def studentsList(request):
    if request.method == "GET":
        stus = Student.objects.all()
        #序列化
        serializer = StudentSerializer(stus, many=True)
        # 不需要指定json格式,返回客戶端可以返回json或者HTML,返回HTML內容的話,會在瀏覽器中經過渲染成頁面
        return Response(serializer.data, status=status.HTTP_200_OK)
    elif request.method == "POST":
        # content = JSONRenderer().render(request.POST)
        # stream = BytesIO(content)
        # stuDict = JSONParser().parse(stream)
        serializer = StudentSerializer(data=request.data)
        if serializer.is_valid():
            #存數據
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response({"error":serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

@api_view(["GET", "PUT", "DELETE"])
def studentDetail(request, pk):
    try:
        stu = Student.objects.get(pk=pk)
    except Student.DoesNotExist as e:
        return Response({"error":str(e)}, status=status.HTTP_404_NOT_FOUND)

    if request.method == "GET":
        serializer = StudentSerializer(stu)
        return Response(serializer.data)
    elif request.method == "PUT":
        # content = JSONRenderer().render(request.POST)
        # stream = BytesIO(content)
        # stuDict = JSONParser().parse(stream)
        # print(stuDict)
        #修改
        serializer = StudentSerializer(stu, data=request.data)
        if serializer.is_valid():
            #存數據
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response({"error":serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == "DELETE":
        stu.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
向URL添加可選的后綴 視圖
def studentsList(request, format=None):
def studentDetail(request, pk, format=None):
路由
from django.conf.urls import url
from myApp import views
#格式后綴
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
    # GET /students/
    # POST /students/
    url(r"^students/$", views.studentsList),
    # GET /students/id
    # PUT /students/id
    # PATCH /students/id
    # DELETE /students/id
    url(r"^students/(?Pd+)/$", views.studentDetail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
測試
http://127.0.0.1:8000/students.api
http://127.0.0.1:8000/students.json
Django RESTful API 之基于類的視圖 把視圖變成類
from myApp.models import Student
from myApp.serializers import StudentSerializer
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from django.http import Http404

class StudentsList(APIView):
    def get(self, request, format=None):
        stus = Student.objects.all()
        serializer = StudentSerializer(stus, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)
    def post(self, request, format=None):
        serializer = StudentSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response({"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

class StudentDetail(APIView):
    def getObject(self, pk):
        try:
            return Student.objects.get(pk=pk)
        except Student.DoesNotExist as e:
            raise Http404
    def get(self, request, pk, format=None):
        stu = self.getObject(pk)
        serializer = StudentSerializer(stu)
        return Response(serializer.data)
    def put(self, request, pk, format=None):
        stu = self.getObject(pk)
        serializer = StudentSerializer(stu, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response({"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
    def delete(self, request, pk, format=None):
        stu = self.getObject(pk)
        stu.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
修改路由匹配類視圖
from django.conf.urls import url
from myApp import views
#格式后綴
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
    # GET /students/
    # POST /students/
    url(r"^students/$", views.StudentsList.as_view()),
    # GET /students/id
    # PUT /students/id
    # PATCH /students/id
    # DELETE /students/id
    url(r"^students/(?Pd+)/$", views.StudentDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
優點

把各種HTTP請求分離開

可以輕松構成可重復使用的行為

可以大大簡化代碼

增加了可讀性

使用Mixins類

基本使用

from myApp.models import Student
from myApp.serializers import StudentSerializer
from rest_framework import mixins, generics

#父類中有且只有一個能繼承自APIView類
class StudentsList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    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 StudentDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    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 myApp.models import Student
from myApp.serializers import StudentSerializer
from rest_framework import generics
class StudentsList(generics.ListCreateAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
class StudentDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
Django RESTful API 之認證和權限

如果沒有權限認證功能,任何資源都會被任何用戶隨意修改,所以實現如下功能

Student與其創建者相互關聯

只有經過身份驗證(登陸)的用戶才可以創建Student對象

只有創建該Student對象的用戶才可以對齊進行更新或者刪除

未經驗證的用戶只有訪問(只讀)的功能

給學生添加所屬用戶字段:owner = models.ForeignKey("auth.User", related_name="students")

重新生成表

創建幾個用戶 python manage.py createsuperuser

在serializers.py文件中給User添加序列化類

from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ("id", "username", "students")
增加用戶的接口

路由

from django.conf.urls import url
from myApp import views
#格式后綴
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
    url(r"^students/$", views.StudentsList.as_view()),
    url(r"^students/(?Pd+)/$", views.StudentDetail.as_view()),

    url(r"^users/$", views.UsersList.as_view()),
    url(r"^users/(?Pd+)/$", views.UserDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)

視圖

from django.contrib.auth.models import  User
class UsersList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
class UserDetail(generics.RetrieveDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
把Student和User關聯

概述: 還不能把Student和User關聯,因為在使用的時候User的數據時通過Request傳入的,而不是以序列化數據傳遞的,此時剛才添加了一個owner作為外鍵,此時使用外鍵

class StudentsList(generics.ListCreateAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    
    #讓用戶在通過post請求創建一個新的student時,在保證創建學生時會把request中的user賦值給該學生的owner字段
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)
在顯示學生時還需要顯示學生屬于哪個用戶
class StudentSerializer(serializers.ModelSerializer):
    class Meta:
        owner = serializers.ReadOnlyField(source="owner.username")
        model = Student
        fields = ("id", "name", "sex", "age", "contend", "isDelete", "grade", "owner")
添加權限
from rest_framework import permissions
class StudentsList(generics.ListCreateAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
    #讓用戶在通過post請求創建一個新的student時,在保證創建學生時會把request中的user賦值給該學生的owner字段
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)
class StudentDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    # 只有所有者用戶才能刪除、修改,其他用戶只能訪問
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
為可瀏覽的API添加登陸功能

工程目錄下與工程目同名目錄下的urls.py文件

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r"^admin/", admin.site.urls),
    url(r"^api-auth/", include("rest_framework.urls", namespace="rest_framework")),
    url(r"^", include("myApp.urls")),
]
添加對象權限

要實現讓所有的Students可以被所有人訪問,但是每個學生只能被其創建者所操作。

需要自定義權限,讓每個學生只能被其創建者所操作,在應用目錄下創建permissions.py的文件

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            # 用戶請求為GET 可以只讀
            return True
        return obj.owner == request.user

添加自定義權限

from myApp.permissions import IsOwnerOrReadOnly
class StudentDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    # 只有所有者用戶才能刪除、修改,其他用戶只能訪問
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly)
API授權

由于現在我們還沒有使用Authentication類,所以項目目前還是使用默認的SessionAuthentication和BaseAuthentication

在使用瀏覽器訪問API的時候,瀏覽器會幫助我們保存會話信息,所以當權限滿足是就可以對一個學生對象進行刪除或者更新,還可以創建學生

當如果通過命令來操作API,我們就必須在每次發送請求是附帶驗證信息 : http://user1:sunck1999@127.0.0.1:8000/students/1/

程序中使用 from django.contrib.auth import login

Django RESTful API 之ViewSet和Routers

目的: 介紹另一種基于類的視圖的寫法,它的抽象程度更高,代碼更少

使用ViewSets重構視圖
from myApp.models import Student
from myApp.serializers import StudentSerializer, UserSerializer
from rest_framework import permissions
from myApp.permissions import IsOwnerOrReadOnly
from django.contrib.auth.models import  User
from rest_framework import viewsets

class StudentViewSet(viewsets.ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly)
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
重構路由
from django.conf.urls import url, include
from myApp.views import StudentViewSet, UserViewSet
from rest_framework.urlpatterns import format_suffix_patterns

students_list = StudentViewSet.as_view({
    "get":"list",
    "post":"create"
})
student_detail = StudentViewSet.as_view({
    "get":"retrieve",
    "put":"update",
    "patch":"partial_update",
    "delete":"destroy"
})
users_list = UserViewSet.as_view({
    "get":"list"
})
user_detail = UserViewSet.as_view({
    "get":"retrieve"
})
urlpatterns = format_suffix_patterns([
    url(r"^students/$", students_list, name="students_list"),
    url(r"^students/(?Pd+)/$", student_detail, name="student_detail"),
    url(r"^users/$", users_list, name="users_list"),
    url(r"^users/(?Pd+)/$", user_detail, name="user_detail"),
])
使用Routers
from django.conf.urls import url, include
from myApp import views
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r"students", views.StudentViewSet)
router.register(r"users", views.UserViewSet)

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/42039.html

相關文章

  • 9-django——restful設計風格

    摘要:設計風格協議與用戶的通信協議,總是使用協議域名應該盡量將部署在專用域名之下,如果確定很簡單,不會有進一步的擴展,可以考慮放在主域名之下。數據庫中的表示記錄同種數據的集合,所以中的名詞也應該使用復數。 showImg(https://segmentfault.com/img/bVbdXlE?w=1560&h=913); RESTful Api設計風格 協議:API與用戶的通信協議,總是使...

    scq000 評論0 收藏0
  • Flask 擴展系列 Flask-RESTful

    摘要:勵以最少的安裝方式進行最佳實踐。上面的例子接收了一個對象并準備將其序列化。裝飾器會通過進行轉換。從對象中提取的唯一字段是。是一個特殊的字段,它接受端點名稱并為響應中的端點生成一個。可以查看項查看完整列表。 大綱 簡介 安裝 快速入門 一個最小的 api 例子 資源豐富的路由 端點 參數解析 數據格式化 完整 TODO 應用例子 簡介 Flask-RESTful是一個Flas...

    阿羅 評論0 收藏0
  • Kubernetes1.5源碼分析(三) apiServergo-restful的使用

    摘要:它包括一組和一個對象,使用進行請求派發。流程基本就是這樣,接著我們直接進入接口看實現拼裝然后填充并返回一個對象創建一個這個是關鍵,會對各種進行注冊增加一個的將該加入到前兩個調用函數比較簡單,這里不進行介紹了。 源碼版本 Kubernetes v1.5.0 go-restful 簡介 go-restful是用于構建REST-style web服務的golang包。它是出現時因為一個jav...

    Doyle 評論0 收藏0
  • Kubernetes1.5源碼分析(二) apiServer資源注冊

    摘要:我們先將上面的接口解析放放,先看下是如何初始化的路徑定義了,再看路徑定義空的創建,用于不同版本對象轉換增加一些轉換函數上面就創建了一個空的。其實就是向添加了轉換函數,比如將轉換為,將轉換為。 源碼版本 Kubernetes v1.5.0 簡介 k8s里面有各種資源,如Pod、Service、RC、namespaces等資源,用戶操作的其實也就是這一大堆資源。但這些資源并不是雜亂無章的,...

    imccl 評論0 收藏0

發表評論

0條評論

Bowman_han

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<