使用ForeignKeys发布模型会导致完整性错误

时间:2013-08-29 05:19:09

标签: tastypie

我正在尝试将评论模型添加到我网站上的其他模型中。这是资源:

class CommentResource(ModelResource):

    user = fields.ForeignKey(UserResource, 'user', readonly=True)
    question = fields.ForeignKey(QuestionResource, 'question', readonly=True)

    def hydrate_user(self, bundle):
        return bundle.request.user

    class Meta:
        queryset = Comment.objects.all().order_by("-created")
        resource_name = 'comment'
        filtering = {
            "session": ALL_WITH_RELATIONS,
            "user": ALL_WITH_RELATIONS
        }
        authorization = CommentAuthorization()

型号:

class Comment(models.Model):

    question = models.ForeignKey(AMAQuestion, related_name = "comments")
    user = models.ForeignKey(User, related_name = "comments")

    created = models.DateTimeField(auto_now_add=True, editable=False)
    edited = models.DateTimeField(auto_now=True, editable=False)

    comment = models.TextField()

尝试POST到此时,似乎tastypie没有正确设置问题。 (由于某种原因,没有调用hydrate_FOO方法也很重要。

以下是我发送的一些示例数据:

{
    "comment": "test",
    "question": "/api/v1/question/1/"
}

这是错误:

Traceback (most recent call last):

  File "C:\Python33\lib\site-packages\django\db\backends\sqlite3\base.py", line
362, in execute
    return Database.Cursor.execute(self, query, params)

sqlite3.IntegrityError: questions_comment.question_id may not be NULL


During handling of the above exception, another exception occurred:


Traceback (most recent call last):

  File "C:\Python33\lib\site-packages\tastypie\resources.py", line 195, in wrapp
er
    response = callback(request, *args, **kwargs)

  File "C:\Python33\lib\site-packages\tastypie\resources.py", line 426, in dispa
tch_list
    return self.dispatch('list', request, **kwargs)

  File "C:\Python33\lib\site-packages\tastypie\resources.py", line 458, in dispa
tch
    response = method(request, **kwargs)

  File "C:\Python33\lib\site-packages\tastypie\resources.py", line 1320, in post
_list
    updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kw
args))

  File "C:\Python33\lib\site-packages\tastypie\resources.py", line 2084, in obj_
create
    return self.save(bundle)

  File "C:\Python33\lib\site-packages\tastypie\resources.py", line 2230, in save

    bundle.obj.save()

  File "C:\Python33\lib\site-packages\django\db\models\base.py", line 546, in sa
ve
    force_update=force_update, update_fields=update_fields)

  File "C:\Python33\lib\site-packages\django\db\models\base.py", line 650, in sa
ve_base
    result = manager._insert([self], fields=fields, return_id=update_pk, using=u
sing, raw=raw)

  File "C:\Python33\lib\site-packages\django\db\models\manager.py", line 215, in
 _insert
    return insert_query(self.model, objs, fields, **kwargs)

  File "C:\Python33\lib\site-packages\django\db\models\query.py", line 1675, in
insert_query
    return query.get_compiler(using=using).execute_sql(return_id)

  File "C:\Python33\lib\site-packages\django\db\models\sql\compiler.py", line 93
7, in execute_sql
    cursor.execute(sql, params)

  File "C:\Python33\lib\site-packages\django\db\backends\util.py", line 41, in e
xecute
    return self.cursor.execute(sql, params)

  File "C:\Python33\lib\site-packages\django\db\backends\sqlite3\base.py", line
364, in execute
    six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.
exc_info()[2])

  File "C:\Python33\lib\site-packages\django\utils\six.py", line 328, in reraise

    raise value.with_traceback(tb)

  File "C:\Python33\lib\site-packages\django\db\backends\sqlite3\base.py", line
362, in execute
    return Database.Cursor.execute(self, query, params)

django.db.utils.IntegrityError: questions_comment.question_id may not be NULL

2 个答案:

答案 0 :(得分:1)

正如您所指出的,readonly是管理水合物循环中属性的属性。它与防止字段在下一个请求中可编辑实际上没有任何关系。如果我理解正确,您希望阻止将来编辑question字段。您可以通过停用资源的修改或控制这些修改来实现此目的。

如果您想阻止修改资源,只需在PUT添加下一行即可停用对{Comment}资源的Meta次来电:

allowed_methods = ['get', 'post',]

另一方面,如果您想控制PUT的行为方式,您可以控制水合物并删除新的问题'来自请求,将停止修改:

def hydrate(self, bundle):
    if bundle.request.method == 'PUT':
        if 'question' in bundle.data:
            bundle.data.pop('question',None)
    return bundle

答案 1 :(得分:0)

事实证明,tastypie甚至没有在第一个POST上设置只读字段。我想这是有道理的,但我仍然想要只在初始POST时可编辑的字段。