REST-framework快速構建API--初體驗

1、快速上手

一、環境準備django

安裝restframework,註冊app

pip install djangorestframework
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'rest_framework',
]

二、urljson

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^publish/', views.PublishView.as_view()),
]

三、models後端

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models

# Create your models here.
from django.db import models

# Create your models here.


class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")
    def __str__(self):
        return self.title

class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name

四、viewsapi

基於CBV方式session

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render,HttpResponse

# Create your views here.
from .models import Publish
from rest_framework.views import APIView

class PublishView(APIView):
    def get(self,request):
 
        #序列化方式4rest_framework
        from rest_framework.response import Response
        publish_list = Publish.objects.all()
        ps = PublishSerializers(publish_list, many=True)
        return Response(ps.data)

    def post(self,request):
        return  HttpResponse('POST')

五、測試app

 

2、結果序列化

API返回結果的形式,json是很是流行的。可是咱們在序列化結果時,有多種方式,每種方式實現的方式不一樣。函數

一、原生json方式

import json
        publish_list = list(Publish.objects.all().values())
        return HttpResponse(json.dumps(publish_list))

 使用json方式對結果進行強轉,先把結果強轉成列表的方式,而後經過json的dumps方式對結果進行格式化。post

注意:測試

這種方式實現最簡單,也能夠自定製須要返回的字段,經過在values中填寫本身須要的字段便可。url

 

二、model_to_dict方法

#序列化方式2
        # from django.forms.models import model_to_dict
        # publish_list = Publish.objects.all()
        # data = []
        # for obj in publish_list:
        #     data.append(model_to_dict(obj))
        # return HttpResponse(data)

  經過models自帶的model_to_dict方法直接把obj對象轉換成字典的形式,而後返回。缺點:須要把每一個對象再次進行處理。

 

三、django自帶的serializers方法

#序列化方式3
        # from django.core import serializers
        # publish_list = Publish.objects.all()
        # data = serializers.serialize("json", publish_list)
        # return HttpResponse(data)

  

3、基於REST-framework序列化

from rest_framework import serializers
class PublishSerializers(serializers.Serializer):
    name=serializers.CharField(max_length=32)
    email=serializers.CharField()


from rest_framework.views import APIView
視圖函數繼承APIView方法
#序列化方式4rest_framework from rest_framework.response import Response publish_list = Publish.objects.all() ps = PublishSerializers(publish_list, many=True) return Response(ps.data)

  

既然有了前面三種方法,爲何這裏還要用restframework的第四種方法呢?緣由以下:

a、對於表結構複雜的狀況,前面三種沒有涉及到,須要咱們本身去經過寫邏輯代碼實現;

b、對於咱們須要的返回表結構中字段的結果,定製也是個問題,好比,咱們的api只須要返回指定的幾個字段;

c、對於咱們後面對資源的操做,好比POST動做,須要對結果進行保存,是否是咱們每次都須要本身寫create方法去保存結果呢?

d、對於錯誤的處理;

等等.....諸如此類的須要考慮的問題,rest-framework都幫咱們寫好了邏輯,只須要咱們去調用便可。

 

對於複雜表結構

from rest_framework import serializers

class BookSerializers(serializers.Serializer):
    title=serializers.CharField(max_length=32)
    price=serializers.IntegerField()
    pub_date=serializers.DateField()
    #一對多,能夠經過source指定列名,默認爲str或unicode方法顯示的
    publish=serializers.CharField(source="publish.name")
    #對於多對多咱們能夠自定義get_field方法,將object添加進去
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        temp=[]
        for author in obj.authors.all():
            temp.append(author.name)
        return temp

 

class BookViewSet(APIView):

    def get(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        
        bs=BookSerializers(book_list,many=True)
        return Response(bs.data)

  注意:這裏的many=True,表示對queryset進行操做,默認爲對model對象進行操做。

4、使用ModelSerializer

class BookSerializers(serializers.ModelSerializer):
      class Meta:
          model=Book
          fields="__all__"
          depth=1

  
保存數據:

def post(self,request,*args,**kwargs):
       
        bs=BookSerializers(data=request.data,many=False)
        if bs.is_valid():
            # print(bs.validated_data)
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)

  經過ModelSerializer方法,相似ModelForm方法,咱們能夠經過Meta類直接指定Model、fields,就能知足咱們的需求。操做哪一個表,提交哪些字段。save方法其實後端是調用的create方法,將咱們提交的數據進行保存。

注意:

在BookSerializers裏面,咱們一樣能夠自定義返回多對多或一對多字段內容;

class BookSerializers(serializers.ModelSerializer):
      class Meta:
          model=Book
          fields="__all__"
          depth=1
publish=serializers.CharField(source="publish.name")
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
        temp=[]
        for author in obj.authors.all():
            temp.append(author.name)
        return temp

  可是這裏若是使用ModelSerializer方法,使用save方法時,ModelSerializer默認自帶的create方法不支持多對多的保存,須要咱們重載create方法:

class BookSerializers(serializers.ModelSerializer):

      class Meta:
          model=Book
          fields="__all__"
          # exclude = ['authors',]
          # depth=1

      def create(self, validated_data):
        
          authors = validated_data.pop('authors')
          obj = Book.objects.create(**validated_data)
          obj.authors.add(*authors)
          return obj

  

5、單條數據操做

針對單條數據進行操做,好比books/1(GET/PUT/DELETE)

class BookDetailViewSet(APIView):

    def get(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj)
        return Response(bs.data)

    def put(self,request,pk):
        book_obj=c
        bs=BookSerializers(book_obj,data=request.data)
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)
    
    def delete(self,request,pk):
        Book.objects.filter(pk=pk).delete()
        return Response()

  

注意:

put進行更新數據時,須要把單條數據的每一個字段寫全,即便以前已是完整的一條記錄,不然會報錯。

  

6、超連接API

class BookSerializers(serializers.ModelSerializer):
      publish= serializers.HyperlinkedIdentityField(
                     view_name='publish_detail',
                     lookup_field="publish_id",
                     lookup_url_kwarg="pk")
      class Meta:
          model=Book
          fields="__all__"
          #depth=1

  

urls

urlpatterns = [
    url(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
    url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
    url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
    url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
]

  

注意:

一、反向解析,經過name進行命名,這個表明前面的URL,無論pk怎麼變化均可以引用;

二、view_name爲反向解析的name,lookup_field爲對應的哪一個字段,這裏的pk對應的是Model裏面的id字段;

三、lookup_url_kwarg是命名url裏面的分組關鍵字;

四、須要在views函數裏面新增一個context={'request':request}

 

class BookView(APIView):
    def get(self,request):
        book_list=Book.objects.all()
        bs=BookModelSerializers(book_list,many=True,context={'request': request})
        return Response(bs.data)
    def post(self,request):
        # post請求的數據
        bs=BookModelSerializers(data=request.data)
        if bs.is_valid():
            print(bs.validated_data)
            bs.save()# create方法
            return Response(bs.data)
        else:
            return Response(bs.errors)

 

 

注意:這裏有一個問題,使用超連接post數據的時候,會有一個報錯:

須要去掉超連接的配置才能POST數據,這裏還沒找到解決辦法。

相關文章
相關標籤/搜索