2012-06-30 53 views
1

我通過tastypie api保存了一個項目時遇到了問題。 (POST方法)Django Tastypie,ManyToMany保存錯誤

這是我的api.py代碼。

from tastypie.resources import ModelResource, ALL, ALL_WITH_RELATIONS 
from tastypie.authorization import DjangoAuthorization 
from tastypie.authentication import BasicAuthentication 
from tastypie import fields 
from apps.clients.models import Client 
from django.contrib.auth.models import User 

class ClientAPI(ModelResource): 
    users = fields.ToManyField('apps.clients.api.ClientUserAPI', 'users',related_name='entry',full=True) 


    class Meta: 
     queryset = Client.objects.all() 
     resource_name="clients" 
     authentication = BasicAuthentication() 
     authorization = DjangoAuthorization() 
     filtering={ 
      "users":ALL 
     } 

    def hydrate_m2m(self,bundle): 
     if bundle.data.get("users"): 
      for user_id in bundle.data["users"]: 
       new_user = User.objects.get(id=user_id) 
       bundle.obj.users.add(new_user) 


class ClientUserAPI(ModelResource): 
    class Meta: 
     queryset = User.objects.all() 
     resource_name = 'users' 
     fields = ['username', 'first_name', 'last_name', 'last_login'] 
     authentication = BasicAuthentication() 
     authorization = DjangoAuthorization() 

當im POST數據,保存成功,但給我錯誤。

{"error_message": "'NoneType' object has no attribute 'obj'", "traceback": "Traceback (most recent call last):\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 192, in wrapper\n response = callback(request, *args, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 397, in dispatch_list\n return self.dispatch('list', request, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 427, in dispatch\n response = method(request, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 1165, in post_list\n updated_bundle = self.obj_create(bundle, request=request, **self.remove_api_resource_names(kwargs))\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 1784, in obj_create\n self.save_m2m(m2m_bundle)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 1942, in save_m2m\n related_mngr = getattr(bundle.obj, field_object.attribute)\n\nAttributeError: 'NoneType' object has no attribute 'obj'\n"} 

當我添加「返回捆綁」行到hydrate_m2m,m2m保存不成功(空白),仍然給我這樣的錯誤。

{"error_message": "'str' object has no attribute 'obj'", "traceback": "Traceback (most recent call last):\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 192, in wrapper\n response = callback(request, *args, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 397, in dispatch_list\n return self.dispatch('list', request, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 427, in dispatch\n response = method(request, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 1165, in post_list\n updated_bundle = self.obj_create(bundle, request=request, **self.remove_api_resource_names(kwargs))\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 1784, in obj_create\n self.save_m2m(m2m_bundle)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 1951, in save_m2m\n related_bundle.obj.save()\n\nAttributeError: 'str' object has no attribute 'obj'\n"} 

當我刪除從代碼hydrate_m2m,返回的錯誤是:

{"error_message": "The URL provided '1' was not a link to a valid resource.", "traceback": "Traceback (most recent call last):\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 192, in wrapper\n response = callback(request, *args, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 397, in dispatch_list\n return self.dispatch('list', request, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 427, in dispatch\n response = method(request, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 1165, in post_list\n updated_bundle = self.obj_create(bundle, request=request, **self.remove_api_resource_names(kwargs))\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 1783, in obj_create\n m2m_bundle = self.hydrate_m2m(bundle)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 743, in hydrate_m2m\n bundle.data[field_name] = field_object.hydrate_m2m(bundle)\n\n File \"/Library/Python/2.7/site-packages/tastypie/fields.py\", line 742, in hydrate_m2m\n m2m_hydrated.append(self.build_related_resource(value, **kwargs))\n\n File \"/Library/Python/2.7/site-packages/tastypie/fields.py\", line 588, in build_related_resource\n return self.resource_from_uri(self.fk_resource, value, **kwargs)\n\n File \"/Library/Python/2.7/site-packages/tastypie/fields.py\", line 522, in resource_from_uri\n obj = fk_resource.get_via_uri(uri, request=request)\n\n File \"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 636, in get_via_uri\n raise NotFound(\"The URL provided '%s' was not a link to a valid resource.\" % uri)\n\nNotFound: The URL provided '1' was not a link to a valid resource.\n"} 

我覺得URL提供的 「1」 是用戶ID。

請告訴我。什麼即時做錯了?

順便說一句,我不太瞭解英語,對不起。

+0

你能在POST變量是什麼添加和你的觀點的相關部分將數據傳遞給模型 – Alvin

回答

7

我敢肯定,您將用戶資源發佈爲逗號分隔的ID。這不是tastypie默認處理相關資源的方式。你應該發佈一個url列表,指向相關資源,就像你的情況一樣 - 像'/ api/v1/users/1'一樣。

或者,您可以將hydrate_m2m更改爲hydrate_users。通用hydrate_m2m遍歷資源中的每個字段,並嘗試將其從url-string轉換爲相關資源的實例(這就是爲什麼您會對「提供的URL」產生錯誤)。 爲hydrate_users的代碼可能是這樣的:

def hydrate_users(self, bundle): 
    try: 
     user_ids = map(int, bundle.data.get('users', [])) 
    except ValueError: 
     raise BadRequest("User ids must be ints") # from tastypie.exceptions 
    bundle.data['users'] = User.objects.filter(id__in=user_ids) 
    return bundle 

希望這有助於

編輯:贊成int卡森刪除拉姆達建議

+0

你是男人! – Anakin

+3

'map(int,bundle.data.get('users',[]))'也可以。爲您節省拉姆達。 – Carson