禁止保存()以防止由于未保存的相关对象“postid”而导致数据丢失
Posted
技术标签:
【中文标题】禁止保存()以防止由于未保存的相关对象“postid”而导致数据丢失【英文标题】:save() prohibited to prevent data loss due to unsaved related object 'postid' 【发布时间】:2016-07-09 04:50:48 【问题描述】:我有如下架构所示的数据库(和模型)情况:
这是模型序列化:
class PostCreateSerializer(serializers.ModelSerializer):
base64image = serializers.CharField(allow_blank=True, required=False)
categories = serializers.ListField(child=serializers.IntegerField(), required=False)
class Meta:
model = Post
fields = ('title', 'text', 'base64image', 'categories')
def create(self, validated_data):
cats = None
if 'categories' in validated_data:
cats = validated_data.pop('categories')
post = Post.objects.create(**validated_data)
if cats is not None:
for cat in cats:
PostCategory.objects.create(postid=post, categoryid=Category.objects.get(id=cat), isprimary=False)
return post
我将这个 json 发送到 api 方法
"title": "Post Test",
"text": "Body post Test",
"categories": [2,4]
但我收到了这个错误:
ValueError: save() prohibited to prevent data loss due to unsaved related object 'postid'.
Internal Server Error: /api/post/create/
Traceback (most recent call last):
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/rest_framework/generics.py", line 192, in post
return self.create(request, *args, **kwargs)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/rest_framework/mixins.py", line 21, in create
self.perform_create(serializer)
File "/Users/alfdev/Lavori/PushApp/Rumorize/server/rumorize/contents/views.py", line 117, in perform_create
PostCategory.objects.create(postid=x, categoryid=Category.objects.get(id=cat), isprimary=False)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/db/models/manager.py", line 122, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/db/models/query.py", line 401, in create
obj.save(force_insert=True, using=self.db)
File "/Users/alfdev/Lavori/PushApp/Rumorize/rvenv/lib/python3.4/site-packages/django/db/models/base.py", line 651, in save
"unsaved related object '%s'." % field.name
ValueError: save() prohibited to prevent data loss due to unsaved related object 'postid'.
我在视图中的 post_create 实现:
def perform_create(self, serializer):
# build and save the image
if 'base64image' in serializer.validated_data:
base64_string = serializer.validated_data.pop('base64image')
import base64
import os
import uuid
base64_format, base64_string = base64_string.split(';base64,')
base64_content = base64.b64decode(base64_string)
filename = ''.format(uuid.uuid4(), utilities.file_extension_from_base64_format(base64_format))
path = os.path.join(MEDIA_ROOT, 'post_photos')
if not os.path.exists(path):
os.makedirs(path)
with open(os.path.join(path, filename), 'wb+') as f:
f.write(base64_content)
serializer.validated_data['image'] = filename
serializer.save(userid=self.request.user, updateuserid=self.request.user, state=1)
更新
现在我得到了这个错误: django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist:帖子没有id。
这些是我的模型:
class Post(models.Model):
id = models.BigIntegerField(db_column='ID', primary_key=True, editable=False)
title = models.CharField(db_column='Title', max_length=500)
text = models.TextField(db_column='Text')
createdate = models.DateTimeField(db_column='CreateDate', editable=False, default=datetime.datetime.now)
updatedate = models.DateTimeField(db_column='UpdateDate', blank=True, null=True, editable=False, default=datetime.datetime.now)
updateuserid = models.ForeignKey(User, models.DO_NOTHING, db_column='UpdateUserID', blank=True, null=True, related_name='PostUpdateUser')
userid = models.OneToOneField(User, models.DO_NOTHING, db_column='UserID', related_name='creation_user')
image = models.CharField(db_column='Image', max_length=500, blank=True, null=True)
state = models.SmallIntegerField(db_column='State')
class Meta:
managed = False
db_table = 'post'
verbose_name = 'Post'
verbose_name_plural = 'Posts'
类 PostCategory(models.Model): id = models.BigIntegerField(db_column='ID', primary_key=True) # 字段名小写。 postid = models.ForeignKey(Post, models.DO_NOTHING, db_column='PostID', related_name='posts_categories') # 字段名小写。 categoryid = models.ForeignKey(Category, models.DO_NOTHING, db_column='CategoryID') # 字段名称小写。 isprimary = models.BooleanField(db_column='IsPrimary') # 字段名称小写。此字段类型是猜测。
class Meta:
managed = False
db_table = 'post_category'
有什么建议吗? 谢谢
【问题讨论】:
感觉你这里的代码和错误不符。您收到错误是因为保存的帖子与 Post.objects.create 相矛盾。 您能更好地解释一下您的意思吗? 如果我的方法不正确,请告诉我如何保存帖子实例和相关类别? 对不起,上面的评论有错别字。我的意思是您收到错误消息,因为该帖子未保存,这与Post.objects.create
行相矛盾。
好的,我理解错误,但您有解决方案吗?
【参考方案1】:
尝试调用ModelSerializer
的create
方法,而不是自己创建对象。此外,if 语句不是必需的,对于 PostCategory,您可以直接使用 id
字段。
class PostCreateSerializer(serializers.ModelSerializer):
base64image = serializers.CharField(allow_blank=True, required=False)
categories = serializers.ListField(child=serializers.IntegerField(), required=False)
class Meta:
model = Post
fields = ('title', 'text', 'base64image', 'categories')
def create(self, validated_data):
# you don't need the if block
cats = validated_data.pop('categories', None)
# try calling the create method of ModelSerializer
post = super(PostCreateSerializer, self).create(validated_data)
if cats is not None:
for cat in cats:
PostCategory.objects.create(postid_id=post.id, categoryid_id=cat, isprimary=False)
return post
【讨论】:
你使用事务吗? 不,我不使用事务 奇怪。这真的是您拥有的完整代码吗?您可以将完整的回溯添加到您的问题吗? 请添加您的perform_create
方法。错误似乎在那里:/Users/alfdev/Lavori/PushApp/Rumorize/server/rumorize/contents/views.py", line 117
在视图中我忘记了导致旧异常的测试,现在我得到了这个错误:django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist: Post has no id.以上是关于禁止保存()以防止由于未保存的相关对象“postid”而导致数据丢失的主要内容,如果未能解决你的问题,请参考以下文章