问题描述
我有一个问题,当我节省一个项目,通过tastypie API。 (POST方法)
i got a problem when i'm saving an item, via tastypie api. (POST method)
下面是我的api.py code。
Here is my api.py code.
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数据,储蓄是成功的,但给我的错误。
when im POST data, saving is successful, but gives me error.
{"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储蓄不成功(空白),仍然给我的错误是这样的。
when i'm add "return bundle" line to hydrate_m2m, m2m saving is not successful (blank), still gives me error like this.
{"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"}
当我从code删除hydrate_m2m,返回的错误是:
when i'm deleting hydrate_m2m from code, returning error is:
{"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"}
我想提供的URL1是用户ID。
i think URL provided "1" is user id.
请告诉我。做什么我错了?
Please tell me. What im doing wrong?
顺便说一句,我不知道英语非常好,对此感到抱歉。
btw, i dont know english very well, sorry for that.
推荐答案
我是pretty肯定的,那您发布的用户资源为逗号分隔的ID。这不是tastypie默认处理与资源的方式。你应该张贴的网址列表,指向相关资源,你的情况 - 像水木清华'/ API / V1 /用户/ 1
I'm pretty sure, that you're posting user resources as comma-separated id's. That's not the way tastypie handles related resources by default. You should post a list of urls, pointing to the related resources, in your case - smth like '/api/v1/users/1'.
另外,您可以hydrate_m2m改为hydrate_users。在你的资源,试图将它从URL字符串转换成相关的资源的一个实例,各个领域的通用hydrate_m2m迭代(这就是为什么你对提供的网址的错误)。
在code为hydrate_users可能是这样的:
Alternatively you can change hydrate_m2m to hydrate_users. Generic hydrate_m2m iterates over every field in you resource and tries to convert it from url-string to an instance of related resource (that's why you get error about the "provided URL").The code for hydrate_users might look like this:
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
卡森建议去除的λ
removed lambda in favour of int
as Carson suggested
这篇关于Django的Tastypie,多对多保存错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!