一、環境準備django
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
API返回結果的形式,json是很是流行的。可是咱們在序列化結果時,有多種方式,每種方式實現的方式不一樣。函數
import json
publish_list = list(Publish.objects.all().values())
return HttpResponse(json.dumps(publish_list))
使用json方式對結果進行強轉,先把結果強轉成列表的方式,而後經過json的dumps方式對結果進行格式化。post
注意:測試
這種方式實現最簡單,也能夠自定製須要返回的字段,經過在values中填寫本身須要的字段便可。url
#序列化方式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對象轉換成字典的形式,而後返回。缺點:須要把每一個對象再次進行處理。
#序列化方式3
# from django.core import serializers
# publish_list = Publish.objects.all()
# data = serializers.serialize("json", publish_list)
# return HttpResponse(data)
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對象進行操做。
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
針對單條數據進行操做,好比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進行更新數據時,須要把單條數據的每一個字段寫全,即便以前已是完整的一條記錄,不然會報錯。
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數據,這裏還沒找到解決辦法。