django-rest-framework是构建web API的一个包,功能强大也很灵活,遵循restful标准,如果对于rest标准还不熟悉,推荐看一下阮一峰的文章
理解restful架构
restful设计指南
django-rest-framework安装
pip install djangorestframework
这篇文章对django-rest-framework有一个详细的综述,如果还不了解可以先看一下这篇文章。我在这里只对serializers.Serializer做一个概述。
1 创建django项目
django-admin startproject serializertutorial
django-admin startapp tutorial
然后在settings.py文件中添加rest_framework和创建的app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'tutorial'
]
接下来配置settings.py文件中django链接数据库的参数,为了定义model。在此之前实现要创建好需要使用的数据库。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django',
'USER':'root',
'PASSWORD':'root',
'HOST':'127.0.0.1',
'PORT':'3306'
}
}
现在配置都做好了,就可以开始工程代码了。
2 创建model
在创建好的app目录下编辑models.py,以创建一个文章model为例
from django.db import models
# Create your models here.
class Article(models.Model):
author=models.CharField(max_length=20)
title=models.CharField(max_length=30)
content=models.TextField()
created=models.DateTimeField(auto_now=True)
class Meta:
ordering=('created',)
def __str__(self):
return self.title
当创建好model之后,就可以开始编写Serializer类了。
Serializer是rest_framework中最简单的序列化基类,封装也是最低的。但是这个基类比较灵活,可以通过这个类来定制我们需要的序列化类。
实现这个类需要重写两个方法,create和update。
简单的理解,create方法对应我们在使用API的时候通过POST来访问的,因为通常通过POST来传递我们需要新建实例的数据。
update方法对应通过PUT/PATCH方法访问API,用来新建实例或者更新已存在的实例,这取决于数据库是否存在我们需要操作的实例。
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
author = serializers.CharField(max_length=20)
title = serializers.CharField(max_length=30)
content = serializers.CharField()
created = serializers.DateTimeField(read_only=True)
def create(self,validated_data):
author = validated_data['author']
title = validated_data['title']
content = validated_data['content']
return Article.objects.create(**validated_data)
def update(self,instance,validated_data):
instance.author=validated_data.get('author',instance.author)
instance.title=validated_data.get('title',instance.title)
instance.content=validated_data.get('content',instance.content)
instance.save()
return instance
在创建ArticleSerializer的时候,创建了一些字段,这些字段代表Serializer类在序列化的时候和model对应的字段。这些字段应该和model里定义的字段同名。
在定义的时候,指定了一些参数,这里只用了read_only,另外还有write_only,required,allow_null/allow_blank,label,help_text,style,error_messages
read_only:表示该字段只能用于API的输出,用户并不能直接指定该字段的值
write_only:这个就和read_only相反,需要用户指定该字段的值
required:该字段是必需的,不能为空
allow_null/allow_blank:该字段允许为null/空
label:标签,用于对字段显示设置
help_text:对字段进行解释的一段文本,用于提示
style:说明字段的类型
error_messages:字段出错时,信息提示
update方法中instancece参数是一个model实例,也可以是一个自定义类实例,其实model也就是一个类,只是在底层封装了一些ORM操作。
至此,自定义的ArticleSerializer类便完成了。下面就是写视图函数来实现API的访问
from django.shortcuts import render
from django.http import HttpResponse,JsonResponse
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from .models import Article
from .serializer import ArticleSerializer
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
@csrf_exempt
def article_list(request):
if request.method=='GET':
articles=Article.objects.all()
serializer=ArticleSerializer(articles,many=True)
return JsonResponse(serializer.data,safe=False)
elif request.method=='POST':
data=JSONParser().parse(request)
serializer=ArticleSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data,status=201)
return JsonResponse(serializer.errors,status=400)
@csrf_exempt
def article_detail(request,aid):
#获取对应的文章
try:
article=Article.objects.get(id=aid)
except:
return HttpResponse(status=404)
if request.method=='GET':
serializer=ArticleSerializer(article)
return JsonResponse(serializer.data,)
if request.method=='PUT':
data=JSONParser().parse(request)
serializer=ArticleSerializer(data=data)
if serializer.is_valid():
print(serializer.validated_data)
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors,status=400)
if request.method=='PATCH':
data=JSONParser().parse(request)
serializer=ArticleSerializer(article,data=data,partial=True)
if serializer.is_valid():
print(serializer.validated_data)
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors,status=400)
if request.method=='DELETE':
article.delete()
return HttpResponse(status=204)
需要注意的一点就是这里希望没有csrf令牌客户端通过POST到这个视图函数,主要添加一个装饰器csrf_exempt.
article_detail方式为了能够向api传参,所以有一个aid参数,代表文章的id。
两个方法的思路总体就是先判断请求的方法。如果是GET,那么就从数据库读取article来序列化再返回到客户端。如果是POST/PUT/PATCH方式,就先需要反序列化传过来的数据,再通过Serializer类实现将数据转化为querydict类型数据格式,并且对数据进行验证。这里并没有做自定义的验证。如果需要自定义验证,需要在Serializer类里面实现。详情参考
article_detail方法中,在对PATCH方式进行处理时,我们希望能够实现部分更新,所有在实例化ArticleSerializer实例时,需要传入一个已存在的model实例。该段代码中已存在的model实例是根据aid查询得到的article。同时指定partial参数为True,表示允许部分更新。
视图函数写好之后,就是配置url
在创建的app目录下创建一个urls.py。我用的是django2.0,所以是通过path函数来配置的,如果是django1.x版本的是通过url函数来配置的
from django.urls import path
from . import views
urlpatterns=[
path('article_list',views.article_list),
path('article_detail/',views.article_detail)
]
django1.x版本
from django.conf.urls import url
from . import views
urlpatterns=[
url(r'article_list',views.article_list),
url(r'article_detail/(?P\d+)',views.article_detail)
]
然后再在项目urls.py文件中导入app的urls
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('tutorial.urls'))
]
运行
python manage.py runserver
然后通过httpie来访问api
httpie安装
pip install httpie
通过POST方式访问 localhost:8000/article_list 接口 来创建一篇文章
然后通过GET访问 localhost:8000/article_list 接口获取所有文章信息
通过GET方式获取指定文章的信息 localhost:8000/article_detail/8