在Django Rest Framework中,我有一个简单的Present
模型,它包含以下字段:
class Present(models.Model):
name = models.CharField(max_length=15)
price = models.FloatField()
link = models.CharField(max_length=15)
isAlreadyBought = models.BooleanField()
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
User
和Present
模型的序列化器就是这些:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'password', 'email')
class PresentSerializer(serializers.ModelSerializer):
user_id = serializers.RelatedField(source='User', read_only=True)
class Meta:
model = Present
fields = ('name', 'link', 'price', 'isAlreadyBought', 'user_id')
def create(self, validated_data, **kwargs):
print(kwargs)
print(validated_data)
return Present.objects.create(**validated_data)
我的目标是,从以下POST请求中保存新的Present
。为此,我在我的请求中添加了user_id
字段,以便将Present
与给定的User
相关联:
import requests
save_present = {'name': 'figurine', 'price': '50.8', 'link': 'fake_link', 'isAlreadyBought': 'True', 'user_id': '22'}
r = requests.post('http://127.0.0.1:8000/present_list', json=save_present)
以下是我尝试保存Present
class PresentList(APIView):
# add a new present
def post(self, request, format=None):
# get user id:
# print(request.data['user_id'])
#
# user = User.objects.get(id=request.data['user_id'])
machin = request.data
# machin.pop('user_id', None)
# machin['user'] = UserSerializer(user).data
print('Machin', machin)
serializer = PresentSerializer(data=machin)
if serializer.is_valid():
print('SERIALIZER OK')
serializer.save()
else:
print(serializer.errors())
return Response('')
我无法找到最好的基于Django的方法来实现这一点,因为我收到此错误:
November 20, 2016 - 19:55:34
Django version 1.10.3, using settings 'tutorial.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
23
Machin {'name': 'figurine', 'link': 'fake_link', 'isAlreadyBought': 'True', 'price': '50.8', 'user': {'password': 'PASSWORD', 'email': 'WESH@wanadoo.fr', 'username': 'Florian'}}
SERIALIZER OK
Internal Server Error: /present_list
Traceback (most recent call last):
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 337, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: blog_present.user_id
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/core/handlers/exception.py", line 39, in inner
response = get_response(request)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/views.py", line 477, in dispatch
response = self.handle_exception(exc)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/views.py", line 437, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/views.py", line 474, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/Florian/PycharmProjects/Backend/tutorial/blog/views.py", line 54, in post
serializer.save()
File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/serializers.py", line 214, in save
self.instance = self.create(validated_data)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/serializers.py", line 902, in create
instance = ModelClass.objects.create(**validated_data)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/query.py", line 399, in create
obj.save(force_insert=True, using=self.db)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/base.py", line 796, in save
force_update=force_update, update_fields=update_fields)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/base.py", line 824, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/base.py", line 908, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/base.py", line 947, in _do_insert
using=using, raw=raw)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/query.py", line 1045, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1054, in execute_sql
cursor.execute(sql, params)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 337, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: blog_present.user_id
[20/Nov/2016 19:55:36] "POST /present_list HTTP/1.1" 500 17246
修改
保存Present
的唯一方法是将blank=True
或/和null=True
添加到ForeignKey
。但是,我希望在保存对象时分配user_id
字段,但此字段不会保留在validated_data
中。我该如何解决这个问题?
答案 0 :(得分:1)
您正在将序列化程序字段设置为read_only
,这意味着在创建或更新对象时,只有在读取对象时才会使用它。
只读字段包含在API输出中,但在创建或更新操作期间不应包含在输入中。任何' read_only'错误地包含在序列化程序输入中的字段将被忽略。将此属性设置为True可确保在序列化表示时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。
http://www.django-rest-framework.org/api-guide/fields/#read_only
另外,请尝试使用PrimaryKeyRelatedField
代替RelatedField
。有关该字段,请参阅documentation。