【python】django中tastypie风格接口设计

需求背景:

使用tastypie原则开发api接口,同时对前面设计的api做适当优化。

tastypie风格接口设计:

  • 1.资源类定义:

from tastypie.authorization import Authorization
from tastypie.resources import ModelResource
from controller.natgw import models
class NatgwResource(ModelResource):
    class Meta:
        authorization = Authorization()
        resource_name = 'natgw'
        list_allowed_methods  = ['get']
        queryset = models.NatGw.objects.all()
        fields = ['ip', 'status', 'vip', 'ospf_status', 'version', 'time', 'gw_version']
  • 2.查询数据列表接口:

uri: /natgw
method: get

上述代码中,fields表示哪些字段需要接口返回;resource_name表示这个资源在url中的名称,跟上述uri的值对应;queryset表示查询的数据库对象;查询接口需要支持按字段过滤,所以需要添加如下代码:

        filtering = {
            'ip': ('exact', 'contains', 'startswith'),
            'status': ('exact', 'in'),
            'vip': ('exact', 'contains', 'startswith'),
            'ospf_status': ('exact', 'in'),
        }

此时如果按照ip模糊匹配196网段的,则url为:/natgw?ip_startswith=196

  • 3.添加数据接口:

uri: /natgw
method: post
data: {}

上述代码已经支持添加数据的接口调用了,此时data中的字段跟数据库中字段有对应的则可保存到数据库中。现在要求添加数据接口只支持数据库中某些字段设置,其他字段不支持在添加时赋值,则需要做一些处理,代码如下:

    def obj_create(self, bundle, **kwargs):
        data = copy.deepcopy(bundle.data)
        bundle.data.clear() #清空data,只设置需要的字段的值
        bundle.data['ip'] = data.get('ip', None)
        bundle.data['agent_port'] = data.get('agent_port', 11111)
        # remove redundant parameters from bundle.data 
        logger.info("Creating object: data2 is: %s" % bundle.data)
        super(NatgwResource, self).obj_create(bundle, **kwargs)
        return

此处应该可以用hydrate处理,但是本人还不是很理解,需要再理解理解。

  • 4.查询数据详情接口:

    查询数据详情时,只要在查询数据列表接口的uri后追加key值即可,如:
uri: /natgw/{keyvalue}
method: get

此处多主键时该当如何处理?大概uuid做主键可以解决。

  • 5.删除数据记录接口:

uri: /natgw/{ip}
method: delete

默认情况下,ip字段不携带时,django框架会清空资源对应的表。此操作极度危险。所以需要对删除操作做一定的处理:

    def obj_delete_list(self, bundle, **kwargs):
        raise NotFound("The URL provided '%s:%s' was not a link to a valid resource." % (bundle.request.path, bundle.request.method))
  • 6.修改数据接口:

uri: /natgw/{ip}
method: put

put方法修改数据时,如果主键被修改,则被认为是新增记录,所以这里需要处理一下:查看基类ModelResource可知,put_detail方法实现了这一功能,而obj_update方法实现了修改数据的功能,如果要修改的对象不存在,则抛出异常给put_detail方法,put_detailNotFound类型的Exception做了新增该数据的处理,可以尝试重载put_detail方法,但是实现上感觉又跟基类方法差别太多。对比put方法和patch方法差异知:

    def patch_detail(self, request, **kwargs):
        """
        Updates a resource in-place.

        Calls ``obj_update``.

        If the resource is updated, return ``HttpAccepted`` (202 Accepted).
        If the resource did not exist, return ``HttpNotFound`` (404 Not Found).
        """

可以尝试使用patch方法看看是否返回对象不存在的错误。验证确实返回404错误。所以修改上述接口定义如下:

uri: /natgw/{ip}
method: patch
  • 7.其他类型接口:

    在设计开发中往往有一些接口不是如上述那样简单的定义就可以完成功能,需要在uri中携带相关参数表明需要完成什么任务,此时该如何处理呢?
    举一个栗子:资源natgw需要单独接口支持enable,那这个接口该如何设计呢?

仔细阅读参考资料中文档,可以找到蛛丝马迹:prepend_urls方法就是用于实现该功能的^^

  def prepend_urls(self):
      return [
          url(r"^(?P<resource_name>%s)/(?P<ip>.*?)/enable%s" % \
              (self.Meta.resource_name, trailing_slash()),
              self.wrap_view('enable_natgw'), 
              name="api_enable_natgw")
      ]

上述代码就可以给natgw增加一个接口,实现方法为enable_natgw

    def enable_natgw(self, request, **kwargs):
        logger.info("Starting ebable natgw, request = %s, kwargs = %s." % (request, kwargs))
        self.method_check(request, allowed=['put'])
        return HttpResponse("OK")

下面使用postman验证一下:

  • step1:
uri: 127.0.0.1:8000/api/v1/natgw/10.1.1/enable
method: patch
  • step2:
uri: 127.0.0.1:8000/api/v1/natgw/10.1.1/enable
method: patch
  • 返回值:1.PUT 2.OK
  • 日志打印内容:
  INFO 2017-03-03 14:21:28,046 resources 12664 12048 Starting ebable natgw, request = <WSGIRequest: PATCH '/api/v1/natgw/10.1.1/enable'>, kwargs = {u'ip': u'10.1.1', u'api_name': u'v1', u'resource_name': u'natgw'}.
  WARNING 2017-03-03 14:21:28,046 basehttp 12664 12048 "PATCH /api/v1/natgw/10.1.1/enable HTTP/1.1" 405 3
  INFO 2017-03-03 14:21:32,947 resources 12664 13052 Starting ebable natgw, request = <WSGIRequest: PUT '/api/v1/natgw/10.1.1/enable'>, kwargs = {u'ip': u'10.1.1', u'api_name': u'v1', u'resource_name': u'natgw'}.
  INFO 2017-03-03 14:21:32,950 basehttp 12664 13052 "PUT /api/v1/natgw/10.1.1/enable HTTP/1.1" 200 2

综上可知自定义的接口以及实现,想要实现相关功能就可以在enable_natgw方法中实现啦^^


参考资料:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容