【发布时间】:2014-09-30 02:25:55
【问题描述】:
我在对以下模型进行 POST 时遇到问题 -
class Tskmst(models.Model):
tskmst_id = models.IntegerField(db_column='tskmst_id', primary_key=True)
tskmst_name = models.CharField(max_length=30)
tskmst_desc = models.TextField(blank=True)
tskmst_type = models.SmallIntegerField(blank=True, null=True)
owner_id = models.ForeignKey(Owner, db_column='owner_id')
tskmst_public = models.CharField(max_length=1, blank=True)
tskmst_lstchgtm = models.DateTimeField(blank=True, null=True)
nodmst_id = models.ForeignKey(Nodmst, db_column='nodmst_id', blank=True, null=True)
servicemst_id = models.ForeignKey(Servicemst, db_column='servicemst_id', related_name='Tskmst_Servicemst_id', blank=True, null=True)
def __unicode__(self):
return self.tskmst_name
class Meta:
managed = False
db_table = 'tskmst'
class Tskmail(models.Model):
tskmail_id = models.ForeignKey(Tskmst, db_column='tskmail_id', related_name='action_email_details', primary_key=True)
tskmail_to_int = models.TextField(blank=True)
tskmail_to_ext = models.TextField(blank=True)
tskmail_subject = models.TextField(blank=True)
tskmail_memo = models.TextField(blank=True) # This field type is a guess.
tskmail_priority = models.SmallIntegerField(blank=True, null=True)
tskmail_attach = models.TextField(blank=True)
class Meta:
managed = False
db_table = 'tskmail'
在 GET 上,它适用于反向关系 - 这是我的序列化程序
class ActionMailSerializer(serializers.ModelSerializer):
class Meta:
model = Tskmail
resource_name = 'tskmail'
fields = ('tskmail_id', 'tskmail_to_int', 'tskmail_to_ext', 'tskmail_subject', 'tskmail_memo',
'tskmail_priority', 'tskmail_attach')
class ActionSerializer(serializers.ModelSerializer):
owner_name = serializers.Field(source='owner_id.owner_name')
nodmst_name = serializers.Field(source='nodmst_id.nodmst_name')
servicemst_name = serializers.Field(source='servicemst_id.servicemst_name')
action_email_details = ActionMailSerializer
class Meta:
model = Tskmst
resource_name = 'tskmst'
depth = 1
fields = ('tskmst_id', 'tskmst_name', 'tskmst_desc', 'tskmst_type', 'owner_name', 'tskmst_public',
'tskmst_lstchgtm', 'nodmst_name', 'servicemst_name', 'action_email_details')
但在 POST 上,它会在验证阶段抱怨以下内容 -
{
"action_email_details": [
{
"tskmail_id": "This field is required."
}
]
}
tskmail_id 肯定存在,我对 PK 与用于反向关系的 FK 不同的其他模型没有问题。我该如何解决这个问题?
如果我将反向关系上的序列化程序代码更改为这样 -
class ActionSerializer(serializers.ModelSerializer):
owner_name = serializers.Field(source='owner_id.owner_name')
nodmst_name = serializers.Field(source='nodmst_id.nodmst_name')
servicemst_name = serializers.Field(source='servicemst_id.servicemst_name')
action_email_details = ActionMailSerializer(required=False)
class Meta:
model = Tskmst
resource_name = 'tskmst'
depth = 1
fields = ('tskmst_id', 'tskmst_name', 'tskmst_desc', 'tskmst_type', 'owner_name', 'tskmst_public',
'tskmst_lstchgtm', 'nodmst_name', 'servicemst_name', 'action_email_details')
然后它在 POST 上给出另一条消息 - RelatedManager 对象不可迭代。
Traceback:
File "D:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
112. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "D:\Python27\lib\site-packages\django\views\generic\base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "D:\Python27\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
57. return view_func(*args, **kwargs)
File "D:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
400. response = self.handle_exception(exc)
File "D:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
397. response = handler(request, *args, **kwargs)
File "D:\Tidal\API\views.py" in put
193. if serializer.is_valid():
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in is_valid
553. return not self.errors
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in errors
545. ret = self.from_native(data, files)
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in from_native
996. instance = super(ModelSerializer, self).from_native(data, files)
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in from_native
368. attrs = self.restore_fields(data, files)
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in restore_fields
283. field.field_from_native(data, files, field_name, reverted_data)
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in field_from_native
472. if serializer.is_valid():
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in is_valid
553. return not self.errors
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in errors
521. identities = [self.get_identity(self.to_native(obj)) for obj in objects]
Exception Type: TypeError at /deploy/action/
Exception Value: 'RelatedManager' object is not iterable
【问题讨论】:
-
您为
ForeignKey字段赋予与db_column相同的名称是否有特殊原因?通常的约定是将字段命名为tskmail,在这种情况下,tskmail_id将是默认的db_column值 - 我怀疑您的问题由此产生。 -
这是一个遗留数据库,因此需要设置列名。按照您的建议,我删除了
db_column='tskmail_id'并将该字段设置为tskmail。再次尝试 POST 失败,KeyError: 'tskmail_id' -
您可能还必须更新您的序列化程序以引用
tskmail-tskmail_id成为一个实现选项,仅当您想读取实际整数 FK 或将其设置在表单上下文。我希望序列化程序类可以通过抽象该细节来正确处理 FK 字段。 -
哦,对了,如果没有一个整数声明的 PK 字段,Django 会很不高兴。这让你的处境变得艰难。作为您描述的解决方法的替代方法,我可能会尝试将
tskmail_id声明为纯粹的整数 PK 字段,并将tskmail声明为带有db_column='tskmail_id'的 ForeignKey。或者看看子类模型在幕后是如何工作的,它们可能有一个 PK 字段,它也是父表的 FK。 -
感谢您的帮助。如果您想发布作为答案,我会接受它,它让我解决了我遇到的问题。
标签: django django-rest-framework