用 Tastypie 覆盖模型字段
Posted
技术标签:
【中文标题】用 Tastypie 覆盖模型字段【英文标题】:Overriding model fields with Tastypie 【发布时间】:2013-07-11 05:09:55 【问题描述】:在我的一个观点中,我定义了一个 mixin 来根据用户的会话详细信息动态设置多个模型(包括客户端模型)的 tech
和 operator
字段,这样用户就不需要手动填写。这个mixin如下:
class GetTechMixin(object):
"""
View mixin that when the form is saved, sets the
site_user and operator.
"""
def form_valid(self, form):
# Get user
user = self.request.user
# Get tech for this user
site_user = SiteUser.objects.get(user=user)
# Override the tech and operator fields
form.instance.tech = site_user
form.instance.operator = site_user.operator
# Save the object
self.object = form.save()
# Return success URL
return HttpResponseRedirect(self.get_success_url())
我还设置了以下 Tastypie API 资源,目的是做同样的事情:
class ClientResource(AbstractModelResource):
class Meta(AbstractModelResource.Meta):
queryset = Client.objects.all()
resource_name = 'client'
def obj_create(self, bundle, **kwargs):
# Get tech for this user
site_user = SiteUser.objects.get(user=bundle.request.user)
# Override the tech and operator fields
bundle.obj.tech = site_user
bundle.obj.operator = site_user.operator
super(ClientResource, self).obj_create(bundle, **kwargs)
但是,这似乎不起作用。使用 PDB 运行它时,我可以将字段添加到 bundle
OK,但是当我让它运行时,它会吐出以下错误:
"error_message": "(1048, \"列'operator_id'不能为空\")", "traceback": "Traceback (最近一次调用最后一次):\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", 第 217 行,在包装器中\n response = callback(request, *args, **kwargs)\n\n 文件\"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", 第 459 行,在 dispatch_list\n return self.dispatch('list', request, **kwargs)\n\n 文件\"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", 第 491 行,在 dispatch\n response = method(request, **kwargs)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", 第 1357 行,在 post_list\n updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs))\n\n 文件 \"/home/matthew/Projects/Myproject/app_api/api.py\",第 49 行,在 obj_create\n super(ClientResource, self).obj_create(bundle, **kwargs)\n\n 文件\"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", 第 2150 行,在 obj_create\n 返回 self.save(bundle)\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", 第 2296 行,在 save\n bundle.obj.save()\n\n 文件中 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/base.py\", 第 546 行,保存\n force_update=force_update, update_fields=update_fields)\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/base.py\", 第 650 行,在 save_base\n 结果 = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/manager.py\", 第 215 行,在 _insert\n 中返回 insert_query(self.model, objs, fields, **kwargs)\n\n 文件\"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/query.py\", 第 1661 行,在 insert_query\n 返回 query.get_compiler(using=using).execute_sql(return_id)\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py\", 第 937 行,在 execute_sql\n cursor.execute(sql, params)\n\n 文件中 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/backends/util.py\", 第 41 行,在执行中\n 返回 self.cursor.execute(sql, params)\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py\", 第 127 行,在执行\n Six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py\", 第 120 行,在执行中\n 返回 self.cursor.execute(query, args)\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/MySQLdb/cursors.py\", 第 201 行,在执行中\n self.errorhandler(self, exc, value)\n\n 文件 \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/MySQLdb/connections.py\", 第 36 行,在 defaulterrorhandler\n 中引发错误类, errorvalue\n\nIntegrityError: (1048, \"列 'operator_id' 不能 空\")\n"
添加字段后,无论是否使用 bundle.obj.save(),我都尝试过,但似乎没有什么不同。
obj_create 是覆盖这些值的正确位置吗?如果是这样,任何人都可以指出我哪里出错了。如果没有,我应该在哪里寻找?
【问题讨论】:
检查site_user.operator
的值
【参考方案1】:
如果有人发现这个,我找到了解决方案。最简单的做法就是用一个新方法覆盖 obj_create 方法,如下所示:
def obj_create(self, bundle, **kwargs):
# Get tech for this user
site_user = SiteUser.objects.get(user=bundle.request.user)
bundle.obj = self._meta.object_class()
for key, value in kwargs.items():
setattr(bundle.obj, key, value)
# Override the tech and operator fields
setattr(bundle.obj, 'tech', site_user)
setattr(bundle.obj, 'operator', site_user.operator)
self.authorized_create_detail(self.get_object_list(bundle.request), bundle)
bundle = self.full_hydrate(bundle)
return self.save(bundle);
【讨论】:
以上是关于用 Tastypie 覆盖模型字段的主要内容,如果未能解决你的问题,请参考以下文章
如何创建作为多个查询联合的 Django 模型字段,以实现覆盖字段?