【发布时间】:2020-03-06 20:55:55
【问题描述】:
我在 models.py 中定义了 Item 模型,如下所示。
class Item(models.Model):
transaction_id = models.CharField(max_length=25, unique=True)
order = models.ForeignKey(Order, on_delete=models.CASCADE)
item_type = models.ForeignKey(ItemType, on_delete=models.SET_DEFAULT, default=1)
title = models.CharField(max_length=200)
description = models.TextField(null=True, max_length=3000)
seller_user_id = models.IntegerField(null=True)
buyer_user_id = models.IntegerField(null=True)
listing_id = models.IntegerField(null=True)
creation_tsz = models.DateTimeField()
price = models.DecimalField(max_digits=9, decimal_places=2)
shipping_cost = models.DecimalField(max_digits=9, decimal_places=2)
quantity = models.IntegerField()
currency_code = models.CharField(null=True, max_length=5)
product_data = JSONField(null=True)
personalization = models.TextField(max_length=1000, null=True)
我还用下面的部分定义了我的 ItemSerializer。
class ItemSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
transaction_id = serializers.CharField(read_only=True, max_length=25)
title = serializers.CharField(max_length=200)
description = serializers.CharField(allow_null=True, max_length=3000)
seller_user_id = serializers.IntegerField(allow_null=True, validators=[validate_positive])
buyer_user_id = serializers.IntegerField(allow_null=True, validators=[validate_positive])
listing_id = serializers.IntegerField(allow_null=True, validators=[validate_positive])
creation_tsz = serializers.DateTimeField()
price = serializers.DecimalField(label='Price', max_digits=9, decimal_places=2, validators=[validate_positive])
shipping_cost = serializers.DecimalField(max_digits=9, decimal_places=2, validators=[validate_positive])
quantity = serializers.IntegerField(read_only=True)
currency_code = serializers.CharField(allow_null=True, max_length=5)
product_data = serializers.CharField(allow_null=True)
personalization = serializers.CharField(max_length=1000, allow_null=True)
def update(self, item:Item, validated_data):
#Validating whether
if 'product_data' in validated_data:
schema_obj = item.item_type.schema
try:
print(validated_data)
jsonschema.validate(
json.loads(validated_data['product_data']),
schema=schema_obj)
except Exception as e:
raise ValidationError({'product_data':[f'Schema for product data is not valid. {str(e)}']})
for key in validated_data:
setattr(item, key, validated_data[key])
item.save()
return item
def validate_product_data(self, value):
"""
Validate whether property is json parsable
:param value:
:return:
"""
try:
cur_obj = json.loads(value)
return value
except Exception as e:
raise ValidationError("This field should be in format of JSON.")
在这个问题中,我希望前端应用程序(一个 VueJS 应用程序)能够根据序列化程序标签和 ValidationError 消息自动显示错误消息对话框。因此,我决定通过更改 settings.py 来使用自定义异常处理程序,如下所示。
....
REST_FRAMEWORK = {
....
'EXCEPTION_HANDLER': 'OrderManagement.utils.exception_handler',
....
}
....
最后异常处理函数如下所示。
def exception_handler(exc, context):
response = views.exception_handler(exc, context)
if isinstance(exc, exceptions.ValidationError):
response.data['validation_meta'] = {key: {'nicename': NICE_NAME_DICT.get(key, key)} for key in exc.detail}
ser = context['view'].get_serializer_class()()
if isinstance(exc, (exceptions.NotAuthenticated)) and response:
response.status_code = status.HTTP_401_UNAUTHORIZED
if response:
response.data['errcode']=response.status_code
return response
我能够将序列化程序放入“ser”变量,但无法获得所有具有“标签”属性的字段。
收集标签和/或 help_text 信息后,我的目标是为我的 VueJS 应用程序生成如下所示的休息响应。
{
"price":[
"Price should be a number"
],
"metadata":{
"price":{
"label":"Price",
"help_text":""
}
}
}
我试图通过创建相关序列化程序的对象并使用“get_fields()”方法来获取它。我还尝试收集有关类属性的字段特定数据。
如何从“ser”变量(即上下文序列化程序)中提取所有字段的“标签”属性?我猜“help_text”属性会用类似的方法收集。
【问题讨论】:
-
您对
label属性有什么特别要求?字段的名称(例如transaction_id或title)?或者是其他东西?添加一些您预期输出的示例将有助于获得答案 -
例如ItemSerializer中的price字段有一个label属性,其值为“Price”。为了生成带有附加元数据字段的 ValidationError 响应,我应该在 exception_handler 中收集标签信息,这样我就可以生成如下所示的 Json 响应。 '{ "price":[ "Price 应该是一个数字" ], "metadata":{ "price":{ "label":"Price", "help_text":"" } } }'
标签: django rest django-rest-framework serialization