一、环境准备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数据,这里还没找到解决办法。