我正在学习 Django Rest Framework 教程,但我被困在第 4 部分。
向视图添加权限后,它说要创建几个片段。我通过可浏览的 API 登录并尝试发布这样的片段:
{
"title": "snippet",
"code": "print 123"
}
当我这样做时,我得到:
完整性错误在/片段/
NOT NULL 约束失败:snippets_snippet.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 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 类中排除。
我今晚正在浏览本教程并遇到了同样的错误。似乎本教程可能落后于实际框架的一个版本左右?无论如何,经过一些研究,我能够获得要保存的片段。
教程说要这样做的地方:
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
您可以在 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)
perform_create在CreateModelMixin中,你的视图应该是泛型的子类。ListCreateAPIView
我有同样的问题。我发现我向SnippetSerializer
中添加了一个perform_create
方法,但它需要添加到SnippetList
视图中,教程中有描述。