实现Django样式API,链接点,继承

时间:2017-01-06 05:55:29

标签: python django

我正在尝试为JSON API实现客户端。我和Django合作过,我发现处理查询的方式非常有趣。

例如:

>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username='johndoe')
>>> user
<User: johndoe>
>>> user.objects.get(username='johndoe')
AttributeError: Manager isn't accessible via User instances

我很感兴趣 Manager 究竟是什么,以及是否有一种简单的方法来实现它。我试着做类似的事情,但失败了。这是我的第一次尝试:

class Api(object):
    def __init__(self, api_key):
        self.api_key = key

    @property
    def player(self):
        return Player(api=self)

class Player(object):
    def __init__(self, api):
        self.api = api

    def get(self, id_):
        '''
        gets json and turns it into dictionary
        '''
        self.name = data['name']
        self.id_ = id_

        return self

所以用法如下:

>>> api = Api('api_key_here')
>>> player = api.player.get('player_id_here')

然而对我而言,这样做会感觉粗略而且完全错误(这当然是正确的)。这里的问题是:

  1. 我必须将整个Api对象发送到Player对象
  2. Player对象仍然会有get()方法
  3. 我不知道使用@property这种方式是否可以接受
  4. 以下是我想如何使用我的Api课程:

    api = Api('api_key_here')
    player = api.player.get('player_id') #getting player object
    item = api.item.get('item_id') #getting item object
    recent_games = api.recent_games.filter(player=player, how_many=10) #getting list of game objects
    

1 个答案:

答案 0 :(得分:2)

我建议您查看https://github.com/samgiles/slumber,它实现了您可能正在做的事情(Rest API客户端)。但即使您正在做其他事情,也会按照您要做的事情实施睡眠。类似的东西:

class RestResource(object):

    def __init__(self, *args, **kwargs):
       self._store = kwargs

    def __call__(self, id=None, action=None):
       """
       Returns a new instance of self modified by one or more of the available
       parameters. These allows us to do things like override format for a
       specific request, and enables the api.resource(ID).get() syntax to get
       a specific resource by it's ID.
       """

       kwargs = {
          'foo': self._store['name1'],
          'bar': self._store['name2']
       }

       return self.__class__(**kwargs)

class Api(object):
   resource_class = RestResource

   def __getattr__(self, item):
      kwargs = {
        'name1': 'val1',
        'name2': 'val2'
      }

      return self.resource_class(**kwargs)

你可以像这样使用

api = Api()
api.player.get()