Django Tastypie,多对多保存错误
Posted
技术标签:
【中文标题】Django Tastypie,多对多保存错误【英文标题】:Django Tastypie, ManyToMany Saving Error 【发布时间】:2012-07-01 19:55:13 【问题描述】:我在保存项目时遇到了问题,通过美味派 api。 (POST 方法)
这是我的 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()
当我发布数据时,保存成功,但给我错误。
"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"
当我将“return bundle”行添加到 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"
我认为提供“1”的 URL 是用户 ID。
请告诉我。我做错了什么?
顺便说一句,我英语不太好,对不起。
【问题讨论】:
您能否添加 POST 变量是什么以及将数据传递给模型的视图的相关部分 【参考方案1】:我很确定,您将用户资源发布为逗号分隔的 id。这不是tastepie 默认处理相关资源的方式。您应该发布一个指向相关资源的 url 列表,在您的情况下 - 类似“/api/v1/users/1”。
或者,您可以将 hydrate_m2m 更改为 hydrate_users。通用 hydra_m2m 遍历资源中的每个字段,并尝试将其从 url-string 转换为相关资源的实例(这就是您收到有关“提供的 URL”的错误的原因)。 hydra_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
希望对你有帮助
编辑:按照 Carson 的建议删除了 lambda 以支持 int
【讨论】:
map(int, bundle.data.get('users', []))
也可以。为您节省 lambda。以上是关于Django Tastypie,多对多保存错误的主要内容,如果未能解决你的问题,请参考以下文章