在视图中使用tastypie资源

6 投票
3 回答
7666 浏览
提问于 2025-04-17 04:29

这是我在这里的第一个问题:

我正在使用tastypie为我的应用程序创建API。

我希望能够使用tastypie来生成JSON格式的数据,然后把这些数据放到Django的视图中,以便我可以启动我的应用数据。

在Django tastypie的食谱中有一个例子,地址是: http://django-tastypie.readthedocs.org/en/latest/cookbook.html#using-your-resource-in-regular-views

问题是我就是无法让它工作,我尝试了从简单到复杂的各种方法,但就是搞不定。这里是我的模型代码:

class ChatMessage(models.Model):
     content = models.TextField()
     added = models.DateTimeField(auto_now_add=True)

     author = models.ForeignKey(ChatUser, related_name="messages")
     chat_session = models.ForeignKey(ChatSession, related_name="messages")
     answer_to = models.ForeignKey('self', blank=True, null=True)

     flagged = models.BooleanField(blank=True,default=False)
     mododeleted = models.BooleanField(blank=True,default=False)
     mododeleted_by = models.ForeignKey(ChatUser,blank=True,null=True,default=None)
     mododeleted_at = models.DateTimeField(blank=True,null=True,default=None)
     [...]

class ChatSession (models.Model):
    title = models.CharField(max_length=200)
    link_title = models.CharField(max_length=200)
    description = tinymce_models.HTMLField()
    date = models.DateTimeField()
    online = models.BooleanField(default=False)
    next_session = models.BooleanField(default=False)
    meps = models.ManyToManyField(ChatMep)
    uid_newsupdate = models.CharField(max_length=200,blank=True,null=True,default="")
    [...]

还有我的资源代码:

class ChatMessageResource(MyModelResource):
    chat_session = fields.ForeignKey(ChatSessionResource, 'chat_session')

    def renderOne(self,request,pkval):
       data =  self.obj_get(None,pk=pkval)
       dbundle = self.build_bundle(obj=data,request=request)
       return self.serialize(None,self.full_dehydrate(dbundle),'application/json')

    def dehydrate(self, bundle):
        bundle.data['likes'] = bundle.obj.get_likes()
        bundle.data['likes_count'] = len(bundle.data['likes'])
        return bundle

    class Meta:
        authentication = Authentication()
        authorization = Authorization()
        queryset = ChatMessage.objects.all()
        resource_name = 'message'
        fields = ('content', 'added', 'flagged', 'mododeleted','author','answer_to','chat_session')
        filtering = {
            'chat_session': ALL_WITH_RELATIONS,
        }

以及我的视图索引代码:

def index(request):

    cur_sess = get_current_chat_session()

    data1= ChatMessageResource().renderOne(request,723)

    return render_to_response('test.html',
                          { 
                            'all_data' : data1 
                           },
                          context_instance=RequestContext(request))

我想要的是我的renderOne()函数能给我返回一个ChatMessageResource的JSON数据。同时,我还希望有一个renderAll()函数能给我返回所有(或过滤后的)ChatMessageResources的JSON数据。

我想使用tastypie的内部功能,我知道我可以自己序列化数据,但这不是我想要的重点。

现在出现的错误是:

NoReverseMatch at /live/

Reverse for 'api_dispatch_detail' with arguments '()' and keyword arguments '{'pk': 14L, 'resource_name': 'session'}' not found.

我快要疯了,已经尝试了好几个小时。

所以请问,如何在Django视图中通过代码使用tastypie获取单个或所有资源的JSON数据!

如果我说得不清楚或者需要进一步解释,请随时问我,谢谢。

其实我想做的是能够通过代码获取我创建的API URL返回的JSON,而不是通过访问这个URL来获取。例如,如果我有/api/v1/messages/?chat_session=14这个URL返回一系列消息,我希望能够通过代码实现同样的效果(而不是通过curl或其他方式去获取这个URL)。

注意:

ModelResource.obj_get的定义可以在这里找到:https://github.com/toastdriven/django-tastypie/blob/master/tastypie/resources.py

def obj_get(self, request=None, **kwargs):
            """
    A ORM-specific implementation of ``obj_get``.

    Takes optional ``kwargs``, which are used to narrow the query to find
    the instance.
    """
            try:
                base_object_list = self.get_object_list(request).filter(**kwargs)
                object_list = self.apply_authorization_limits(request, base_object_list)
                stringified_kwargs = ', '.join(["%s=%s" % (k, v) for k, v in kwargs.items()])

                if len(object_list) <= 0:
                    raise self._meta.object_class.DoesNotExist("Couldn't find an instance of '%s' which matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs))
                elif len(object_list) > 1:
                    raise MultipleObjectsReturned("More than '%s' matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs))

                return object_list[0]
            except ValueError:
                raise NotFound("Invalid resource lookup data provided (mismatched type).")

3 个回答

0

你的问题似乎出在这里:

data =  self.obj_get(None,pk=pkval)

传给 obj_get 的参数应该是可以直接传给标准的 get 的关键字参数(kwargs)。里面不应该有 None

2

我发现 obj_get 方法需要一个打包好的 request 对象。可以查看这个链接了解更多。

def user_detail(request, username):
    ur = UserResource()
    # Add this request bundle to the obj_get() method as shown.
    req_bundle = ur.build_bundle(request=request)
    user = ur.obj_get(req_bundle, username=username)
    ....
10

我找到了解决办法,问题出在网址解析上……我需要把

def get_resource_uri(self, bundle_or_obj):
   return '/api/v1/%s/%s/' % (self._meta.resource_name,bundle_or_obj.obj.id)

加到相关的对象(这里是会话)里,这样才能正常工作(别问为什么!)

下面是我用来处理renderDetail和renderList的有效方案:

def renderDetail(self,pkval):
    request = HttpRequest()
    request.GET = {'format': 'json'}
    resp =  self.get_detail(request, pk=pkval)
    return resp.content


def renderList(self,options={}):
    request = HttpRequest()
    request.GET = {'format': 'json'}
    if len(options) > 0:
        request.GET.update(options)

    resp = self.get_list(request)
    return resp.content

这里是一个使用示例:

cmr = ChatMessageResource()

dataOne= cmr.renderDetail("723")

dataAll = cmr.renderList({'limit':'0','chat_session':cur_sess.pk})

撰写回答