如何从 Django Rest Framework 序列化程序中提取"label"和"help_text"数据?



我在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"变量中,但无法获取所有具有"label"属性的字段。

在收集标签和/或help_text信息后,我的目标是为我的VueJS应用程序生成如下的rest响应。

{
"price":[
"Price should be a number"
],
"metadata":{
"price":{
"label":"Price",
"help_text":""
}
}
} 

我试图通过创建相关序列化程序的对象并使用"get_fields(("方法来获得它。我还尝试收集类属性的字段特定数据。

如何从"ser"变量(即上下文序列化程序(中提取所有字段的"label"属性?我想"help_text"属性将使用类似的方法收集。

下面的代码运行得很好。首先,应该实例化ItemSerializer中的一个对象,字段字典中的所有字段都有标签和help_text数据。

def exception_handler(exc, context):
response = views.exception_handler(exc, context)
if isinstance(exc, exceptions.ValidationError):
ser = context['view'].get_serializer_class()
ser_obj = ser()
response.data['validation_meta'] = {}
for key in exc.detail:
if key in ser_obj.fields:
response.data['validation_meta'][key] = {'label': ser_obj.fields[key].label, 'help_text': ser_obj.fields[key].help_text}
if isinstance(exc, (exceptions.NotAuthenticated)) and response:
response.status_code = status.HTTP_401_UNAUTHORIZED
if response:
response.data['errcode']=response.status_code
return response

最新更新