利用Django实现RESTful API

  RESTful API现在很流行,这里是它的介绍理解RESTful架构和RESTful API设计指南.按照Django的常规方法当然也可以实现REST,但有一种更快捷、强大的方法,那就是Django RESTframework.它是python的一个模块,通过在Django里面配置就可以把app的models中的各个表实现RESTful API。下面是实现方法:

一、安装配置

pipinstalldjangorestframeworkpipinstallmarkdown#MarkdownsupportforthebrowsableAPI.pipinstalldjango-filter#Filteringsupport

再到Django的settings.py中的INSTALLED_APPS添加rest_framework,如下:

1234INSTALLED_APPS=(...'rest_framework',)

在根目录的url.py文件中为rest_framework框架的login和logout视图添加url:

1234urlpatterns=[...url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))]

二、创建model和Serializer

创建app,名为snippets.。在视图 models.py 中添加一张表如下:

fromdjango.dbimportmodelsfrompygments.lexersimportget_all_lexers#一个实现代码高亮的模块frompygments.stylesimportget_all_stylesLEXERS=[itemforiteminget_all_lexers()ifitem[1]]LANGUAGE_CHOICES=sorted([(item[1][0],item[0])foriteminLEXERS])#得到所有编程语言的选项STYLE_CHOICES=sorted((item,item)foriteminget_all_styles())#列出所有配色风格classSnippet(models.Model):created=models.DateTimeField(auto_now_add=True)title=models.CharField(max_length=100,blank=True,default='')code=models.TextField()linenos=models.BooleanField(default=False)language=models.CharField(choices=LANGUAGE_CHOICES,default='python',max_length=100)style=models.CharField(choices=STYLE_CHOICES,default='friendly',max_length=100)classMeta:ordering=('created',)


然后开始同步到数据库中:

./manage.pymakemigrationssnippets./manage.pymigrate

接下来需要做的就是创建Serializer类,类似于 Form。它的作用就是从你传入的参数中提取出你需要的数据,并把它转化为 json 格式(注意,已经是字节码了),同时支持反序列化到model对象。在snippets 文件夹中添加serializers.py并在其添加如下:

fromrest_frameworkimportserializersfromsnippets.modelsimportSnippet,LANGUAGE_CHOICES,STYLE_CHOICESclassSnippetSerializer(serializers.Serializer):#它序列化的方式很类似于Django的formsid=serializers.IntegerField(read_only=True)title=serializers.CharField(required=False,allow_blank=True,max_length=100)code=serializers.CharField(style={'base_template':'textarea.html'})#style的设置等同于Django的widget=widgets.Textarealinenos=serializers.BooleanField(required=False)#用于对浏览器的上的显示language=serializers.ChoiceField(choices=LANGUAGE_CHOICES,default='python')style=serializers.ChoiceField(choices=STYLE_CHOICES,default='friendly')defcreate(self,validated_data):"""Createandreturnanew`Snippet`instance,giventhevalidateddata."""returnSnippet.objects.create(**validated_data)defupdate(self,instance,validated_data):"""Updateandreturnanexisting`Snippet`instance,giventhevalidateddata."""instance.title=validated_data.get('title',instance.title)instance.code=validated_data.get('code',instance.code)instance.linenos=validated_data.get('linenos',instance.linenos)instance.language=validated_data.get('language',instance.language)instance.style=validated_data.get('style',instance.style)instance.save()returninstance

三、使用Serializer

先使用 ./manage.py shell 进入Django的shell中。操作如下:

可以看到 Serializer 的使用如同 Django 的 forms.它的反序列化如下:

fromdjango.utils.siximportBytesIOstream=BytesIO(content)data=JSONParser().parse(stream)

这是再把得到的数据转化为实例:

serializer=SnippetSerializer(data=data)serializer.is_valid()#开始验证#Trueserializer.validated_data#OrderedDict([('title',''),('code','print"hello,world"\n'),('linenos',False),('language','python'),('style','friendly')])serializer.save()#<Snippet:Snippetobject>

同时,我们还可以对 querysets 进行序列化,只需简单地在设置参数many=True,如下:

serializer=SnippetSerializer(Snippet.objects.all(),many=True)serializer.data#[OrderedDict([('id',1),('title',u''),('code',u'foo="bar"\n'),('linenos',False),('language','python'),('style','friendly')]),OrderedDict([('id',2),('title',u''),('code',u'print"hello,world"\n'),('linenos',False),('language','python'),('style','friendly')]),OrderedDict([('id',3),('title',u''),('code',u'print"hello,world"'),('linenos',False),('language','python'),('style','friendly')])

四、使用ModelSerializer

ModelSerializer类似于Django的 modelform, 可以直接关联到models中的表。如下:

classSnippetSerializer(serializers.ModelSerializer):classMeta:model=Snippetfields=('id','title','code','linenos','language','style')

五、在Django的视图中使用Serializer

首先,可以像常规Django视图的写法一样写,返回序列化的输出数据。

fromdjango.httpimportHttpResponse,JsonResponsefromdjango.views.decorators.csrfimportcsrf_exemptfromrest_framework.renderersimportJSONRendererfromrest_framework.parsersimportJSONParserfromsnippets.modelsimportSnippetfromsnippets.serializersimportSnippetSerializer@csrf_exemptdefsnippet_list(request):"""Listallcodesnippets,orcreateanewsnippet."""ifrequest.method=='GET':snippets=Snippet.objects.all()serializer=SnippetSerializer(snippets,many=True)returnJsonResponse(serializer.data,safe=False)elifrequest.method=='POST':data=JSONParser().parse(request)serializer=SnippetSerializer(data=data)ifserializer.is_valid():serializer.save()returnJsonResponse(serializer.data,status=201)returnJsonResponse(serializer.errors,status=400)

也可以写一个视图对应其models中的表,实现对它的删、改、查。

@csrf_exemptdefsnippet_detail(request,pk):"""Retrieve,updateordeleteacodesnippet."""try:snippet=Snippet.objects.get(pk=pk)exceptSnippet.DoesNotExist:returnHttpResponse(status=404)ifrequest.method=='GET':serializer=SnippetSerializer(snippet)returnJsonResponse(serializer.data)elifrequest.method=='PUT':data=JSONParser().parse(request)serializer=SnippetSerializer(snippet,data=data)ifserializer.is_valid():serializer.save()returnJsonResponse(serializer.data)returnJsonResponse(serializer.errors,status=400)elifrequest.method=='DELETE':snippet.delete()returnHttpResponse(status=204)

添加对应的url,snippets/urls.py中设置如下:

fromdjango.conf.urlsimporturlfromsnippetsimportviewsurlpatterns=[url(r'^snippets/$',views.snippet_list),url(r'^snippets/(?P<pk>[0-9]+)/$',views.snippet_detail),]

最后还要在根目录的 url.py 中添加对应的映射。

urlpatterns=[    ...url(r'^',include('snippets.urls')),]

这时,所有的配置已经完成了。接下来就是测试我们的API

六、测试API

为了方便我们可以使用 httpie 模块来测试,启动Django,再在客户端输入http://127.0.0.1:8000/snippets/,操作如下:

还可以进行put操作,修改对应的内容