【问题标题】:Rest Framework Tutorial IntegrityError creating snippetsRest Framework 教程 IntegrityError 创建片段
【发布时间】:2014-11-25 23:18:58
【问题描述】:

我正在学习 Django Rest Framework 教程,但我被困在第 4 部分。

为视图添加权限后,它说要创建几个 sn-ps。我通过可浏览的 API 登录并尝试像这样发布一个 sn-p:

{
"title": "snippet",
"code": "print 123"
}

当我这样做时:

/sn-ps/ 处的完整性错误

NOT NULL 约束失败:sn-ps_sn-p.owner_id

有人知道这里发生了什么吗?

Traceback:
File "/home/grez/restenv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/grez/restenv/lib/python3.4/site-packages/django/views/decorators/csrf.py" in wrapped_view
  57.         return view_func(*args, **kwargs)
File "/home/grez/restenv/lib/python3.4/site-packages/django/views/generic/base.py" in view
  69.             return self.dispatch(request, *args, **kwargs)
File "/home/grez/restenv/lib/python3.4/site-packages/rest_framework/views.py" in dispatch
  403.             response = self.handle_exception(exc)
File "/home/grez/restenv/lib/python3.4/site-packages/rest_framework/views.py" in dispatch
  400.             response = handler(request, *args, **kwargs)
File "/home/grez/web/resttutorial/snippets/views.py" in post
  23.             serializer.save()
File "/home/grez/restenv/lib/python3.4/site-packages/rest_framework/serializers.py" in save
  599.             self.save_object(self.object, **kwargs)
File "/home/grez/restenv/lib/python3.4/site-packages/rest_framework/serializers.py" in save_object
  1041.         obj.save(**kwargs)
File "/home/grez/web/resttutorial/snippets/models.py" in save
  36.         super(Snippet, self).save(*args, **kwargs)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/models/base.py" in save
  591.                        force_update=force_update, update_fields=update_fields)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/models/base.py" in save_base
  619.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/models/base.py" in _save_table
  700.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/models/base.py" in _do_insert
  733.                                using=using, raw=raw)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/models/manager.py" in manager_method
  92.                 return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/models/query.py" in _insert
  921.         return query.get_compiler(using=using).execute_sql(return_id)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in execute_sql
  920.                 cursor.execute(sql, params)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  81.             return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  65.                 return self.cursor.execute(sql, params)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/utils.py" in __exit__
  94.                 six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/grez/restenv/lib/python3.4/site-packages/django/utils/six.py" in reraise
  549.             raise value.with_traceback(tb)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  65.                 return self.cursor.execute(sql, params)
File "/home/grez/restenv/lib/python3.4/site-packages/django/db/backends/sqlite3/base.py" in execute
  485.         return Database.Cursor.execute(self, query, params)

Exception Type: IntegrityError at /snippets/
Exception Value: NOT NULL constraint failed: snippets_snippet.owner_id

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    似乎答案取决于 Django REST 框架版本。下面的答案已经在 3.2.4 和 3.10.3 版本上进行了测试。如果您使用这些版本和基于类的视图,您应该输入:

    serializer.save(owner=self.request.user)
    

    而不是

    serializer.save()
    

    在 SnippetList.post() 方法中,使其如下所示:

    def post(self, request, format=None):
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(owner=self.request.user)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    

    函数 pre_create() 应该从 SnippetList 类中排除。

    【讨论】:

      【解决方案2】:

      我今晚正在阅读本教程,但遇到了同样的错误。看来本教程可能是实际框架后面的一个版本?无论如何,经过一番研究,我能够得到 sn-ps 来保存。

      教程说要这样做:

      def perform_create(self, serializer):
          serializer.save(owner=self.request.user)
      

      我切换到这个:

      def pre_save(self, snip):
          snip.owner = self.request.user
      

      似乎perform_create 方法不再存在或被调用,所以owner 永远不会被设置,因此我们看到了错误。我不确定我所做的是否是正确解决问题的方法,但它似乎有效!

      这是我发现上述内容的文档的链接:http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview

      【讨论】:

      • 非常感谢!我确信 perform_create() 一定不正确,但我不确定如何检查或使用什么方法。很好的答案!
      • 对。第一次回答问题。 :)
      • 我认为 pre_save 是旧方法:“注意:这些方法取代了旧式 2.x 版本的 pre_save、post_save、pre_delete 和 post_delete 方法,这些方法不再可用。” django-rest-framework.org/api-guide/generic-views
      • 您使用哪些类来实现视图? perform_create 由CreateModelMixin.create method 调用,如文档所述,因此您必须从该mixin 继承您的视图。例如。 ModelViewSet 会自动使用它,但 GenericApiView 不会。
      【解决方案3】:

      您可以在 SnippedList 的 post 方法中更新 save() 参数:

      def post(self, request, format=None):
          serializer = SnippetSerializer(data=request.data)
          if serializer.is_valid():
              serializer.save(owner=self.request.user)
              return Response(serializer.data, status=status.HTTP_201_CREATED)
          return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
      

      【讨论】:

        【解决方案4】:

        perform_create 在 CreateModelMixin 中,你的视图应该是 generics.ListCreateAPIView 的子类

        【讨论】:

          【解决方案5】:

          我也有同样的问题。我发现我在SnippetSerializer 中添加了一个perform_create 方法,但它需要在SnippetList 视图中添加,它在教程中有描述。

          【讨论】:

            猜你喜欢
            • 2013-12-25
            • 1970-01-01
            • 1970-01-01
            • 2018-09-19
            • 1970-01-01
            • 1970-01-01
            • 2014-02-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多