Django 利用 API 实现 AJAX 操作

Django的缺点之一,就是它不支持AJAX。好吧,我知道这么一说又会有一群人反驳:Django有各种模块可以提供AJAX功能;写一个XML的view来实现AJAX;整合pyjams就什么功能都有了云云。嘛,都可以,我这也只是分享一个可行的方案,并不是唯一的。如果这个方案正好适合你的项目,那直接拿去用不是更省时间吗?

首先说一下现在项目的情况,前端工程师想用AJAX的方式(依赖于jQuery),通过POST/GET/PUT请求,提交JSON/XML/YAML格式的数据给后台数据库暴露出的一个API地址,以实现对后台数据的操作。如果在view里写一个函数来做比较麻烦,所以使用tastypie直接根据定义的model生成一个API。

Install&Begin

需要安装django-tastpiepython-digestpython-dateutilmimeparse。最近因为某些原因国外的https访问经常会受到影响,所以附上下载链接。当然能用pip/easy_install之类的命令来安装最好,已经给出了模块名,这里不再重复写一次命令了。

还是和以前一样,先以最快的方式先把tastypie跑起来:

创建名为products应用为例,需要编辑products/models.py,新建products/api.py,然后编辑项目的urls.py:
products/models.py范例用,超简单,没什么可说的。

from django.db import models
class Product(models.Model):
    name = models.CharField(max_length=16)
    brand = models.CharField(max_length=32)
    def __unicode__(self):
        return self.title

products/api.py

from tastypie.resources import ModelResource
from accounts.models import Product
class ProductResource(ModelResource):
    class Meta:
        queryset = Product.objects.all()
        resource_name = 'p' #可选,不设置的话默认为product

urls.py,引入在api中定义的ProductResource

from django.conf.urls.defaults import patterns, include, url
from accounts.api import ProductResource
urlpatterns = patterns('',
    url(r'^api/', include(ProductResource().urls)),
)

api定义完成,访问http://127.0.0.1:8000/api/p/?format=json可以看到JSON格式的数据,如右图。因为我装了JSONView for chrome,所以输出的JSON格式比默认的友好一些。

models.py和urls.py都是基础配置,所以主要说一下api.py。这里使用了ModelResource而不是Django提供的Resource,这样就脱离了Django的ORM,提供了扩展到NOSQL的可能性。网上有一个名为tastymongo的项目,作者的目的似乎是想实现tastypie和mongodb的整合,但是一直没有更新,所以我们项目中是直接利用mongoengine将这两者整合在一起。

POST & INSERT

以POST请求发送一个JSON数据给/api/p/这个地址实现数据的添加,在views.py中建立一个简单的函数,载入product/add.htm模板。html代码如下:

<html>
  <head>
    <title>Tastyapi</title>
  </head>
  <body>
    <form>
      <input type="text" id="brand" />
      <input type="text" id="name" />
      <input type="button" onclick="ajax_insert()" value="insert" />
    </form>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" ></script>
  <script type="text/javascript" >

  function ajax_insert()
  {
    var pname = $('#name').val();
    var pbrand = $('#brand').val();
    $.ajax({
      type : "POST", //要插入数据,所以是POST协议
      url : "/api/p/", //注意结尾的斜线,否则会出现500错误
      data : '{"name" : "'+pname+'", "brand" : "'+pbrand+'"}', //JSON数据
      success: function(){
        alert('Submit Success')
      },
      dataType : 'json', //在ie浏览器下我没有加dataTpye结果报错,所以建议加上
      contentType : 'application/json',
    });
  }
  </script>
  </body>
</html> 

这个时候如果进行操作,会返回401错误,因为还没有进行用户验证。毕竟api涉及对后台数据的操作,如果不验证提交者的身份,对于网站安全来说不是什么好事。要实现验证唯一需要修改的是api.py文件:

from tastypie.resources import ModelResource
from accounts.models import Product
from tastypie.authentication import BasicAuthentication
from tastypie.authorization import DjangoAuthorization
class ProductResource(ModelResource):
    class Meta:
        queryset = Product.objects.all()
        resource_name = 'p'
        authorization = DjangoAuthorization()
        #authorization = Authorization()
        #authentication = BasicAuthentication()

设置只有只有登录的用户能通过API操作数据。L10的Authorization()验证方式是允许任何人使用这个API,L11的BasicAuthentication()是使用 HTTP的验证方式,就是我们常看到的,弹出一个难看的文本框,然后然你输入用户名和密码,这种验证方式不太友好,通常不会提供给普通用户使用。

PUT & DELETE

切换AJAX的请求为PUT或DELETE,可以进行更新或是删除操作,但要指定唯一的id或是slug:

 function ajax_delete()
  {
    $.ajax({
      type : "DELETE",
      url : "/api/p/1/", #删除id为1的记录
      success: function(){
        alert('Submit Success')
      },
    dataType : 'json',
    contentType : 'application/json',
    });
  }

更新操作使用PUT请求,可以直接参考手册,和添加操作相比,它要指定唯一的slug或是id;和删除操作相比,它要加上提交的data。

Afterword

Django是一个开放的框架,虽然它已经解决了很多问题,但本身确实有很多做得不够好的地方,不妨碍我们去选择更适合自己的方案。tastypie很适合团队分工合作,即使是完全不懂Django的前端,一样能通过API进行操作,而且可以与NOSQL数据库配合使用,至于其他的功能和用法期待大家挖掘吧。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。