Django REST Framework OPTIONS请求如何返回字段默认值
DRF OPTIONS接口携带字段默认值的实现
DRF 本身内置支持在OPTIONS接口中返回字段默认值,你当前返回结构里没有这个信息,本质是序列化器到元数据生成的链路没有把默认值正确传递出去,完全不需要从零写自定义逻辑拼接返回结构。
为什么现在看不到默认值字段
OPTIONS接口里actions.POST下的字段描述,是DRF默认的DefaultMetadata元数据类,从序列化器字段上读取公开属性拼接生成的。
只要序列化器字段明确设置了default参数,框架就会自动把这个值放到返回结构里,不需要额外处理。
很多人遇到返回里缺失默认值,基本都是两个常见原因:
- 写序列化器的时候手动重写了字段:比如为了调整choices的文案,单独在序列化器里定义了
delivery_method = serializers.ChoiceField(choices=...),但是忘了把模型上的default=DELIVERY_METHOD__SHIPPING_ONLY参数同步写到序列化器字段的定义里,导致元数据类根本读不到默认值 - 用的DRF版本在3.10之前:这个版本的
DefaultMetadata原生逻辑就没有把default属性加入到返回的字段信息里
内置能力生效的正确写法
只要你给对应序列化器字段明确加上default参数,不管是ModelSerializer自动映射的字段,还是手动定义的字段,符合当前DRF版本的元数据读取规则的话,OPTIONS返回里就会自动多出default节点。
举个实际的字段定义例子:
from rest_framework import serializers class StoreConfigSerializer(serializers.ModelSerializer): # 手动定义字段时,把default值和模型定义保持一致 delivery_method = serializers.ChoiceField( choices=DELIVERY_METHOD_CHOICES, default=DELIVERY_METHOD__SHIPPING_ONLY, label="Delivery method" ) class Meta: model = StoreConfig fields = ["delivery_method"]
这种写法下,OPTIONS接口返回的字段结构会自动补充默认值信息:
"delivery_method": { "type": "choice", "required": false, "read_only": false, "label": "Delivery method", "default": "shipping_only", "choices": [ {"value": "shipping_only", "display_name": "Shipping only"}, {"value": "local_pickup_only", "display_name": "Local pickup only"}, {"value": "shipping_and_local_pickup", "display_name": "Shipping & local pickup"} ] }
注意:如果字段的默认值是可调用对象(比如
default=datetime.now这类动态计算的函数),DRF不会自动调用函数取执行结果返回,只会返回可调用对象的字符串表示,这种场景需要自己稍微调整下元数据的取值逻辑。
低版本DRF的兼容处理
如果用的DRF版本比较老,没有自动返回default的能力,不需要硬升级框架,只要写几行自定义的元数据类,全局替换默认的元数据逻辑就行:
from rest_framework.metadata import DefaultMetadata class CustomDefaultMetadata(DefaultMetadata): def get_field_info(self, field): # 继承原有逻辑,拿到基础的字段描述 field_base_info = super().get_field_info(field) # 过滤只读字段、无实际默认值的字段,把真实默认值加到返回结构里 if not field.read_only and field.default is not None and field.default != "": field_base_info["default"] = field.default return field_base_info
写完之后在DRF的全局配置里指定这个自定义类即可生效:
REST_FRAMEWORK = { "DEFAULT_METADATA_CLASS": "你的模块路径.CustomDefaultMetadata", }
前端拿到返回结构后,只要读取对应字段下的default值,直接设置为select选择框的初始选中项,就能完成自动预填,不需要把默认值硬编码在前端代码里。
内容的提问来源于stack exchange,提问作者Milano

