Django DRF序列化关联URLField 如何返回纯URL列表而非字典对象
基于Django REST Framework序列化器开发时,需要实现模型存储用户搜索产生的URL列表,通过序列化器返回对应URL的组合内容。目前参考官方文档及相关社区问答已完成基础功能开发,但返回格式不符合预期:需要解包DRF响应中嵌套的字典列表。
当前API输出效果:
当前返回的links字段为带link键的字典列表,结构为[{"link": "url1"}, {"link": "url2"}],预期links字段直接输出纯URL字符串列表,结构为["url1", "url2"]。
现有代码
models.py(精简版本)
class User(AbstractUser): pass class Combo(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='searches') updated = models.DateTimeField(auto_now = True) created = models.DateTimeField(auto_now_add = True) class ComboLink(models.Model): combo = models.ForeignKey('Combo', on_delete=models.CASCADE, related_name='links') link = models.URLField(null=True, blank=True)
serializers.py
class ComboLinkSerializer(ModelSerializer): class Meta: model = ComboLink fields = ['link'] class ComboSerializer(ModelSerializer): links = ComboLinkSerializer(many=True) class Meta: model = Combo fields = ['user', 'id', 'created', 'links']
返回嵌套字典的核心原因是使用了完整的模型序列化器做关联嵌套,该序列化器默认会将每个关联对象序列化为包含对应字段的字典。要实现纯字符串列表输出,有两种可直接落地的实现方案:
方案1:使用SlugRelatedField(优先选择,代码最简洁)
无需单独定义ComboLinkSerializer,直接在ComboSerializer中使用SlugRelatedField指定提取关联对象的link字段值即可。
修改后的serializers.py代码:from rest_framework.serializers import ModelSerializer, SlugRelatedField class ComboSerializer(ModelSerializer): links = SlugRelatedField( many=True, read_only=True, slug_field='link' ) class Meta: model = Combo fields = ['user', 'id', 'created', 'links']该配置会自动遍历所有关联的
ComboLink对象,提取每个对象的link属性值,直接返回纯字符串格式的URL列表。如果需要支持写入操作(创建/更新Combo时同步提交URL列表生成关联记录),只需移除read_only=True,补充对应create/update方法处理关联对象的创建逻辑即可。方案2:重写关联序列化器的to_representation方法
如果后续需要扩展ComboLink的序列化逻辑,可以保留原有ComboLinkSerializer,重写其to_representation方法,直接返回link字段值而非字典结构:class ComboLinkSerializer(ModelSerializer): class Meta: model = ComboLink fields = ['link'] def to_representation(self, instance): return instance.link class ComboSerializer(ModelSerializer): links = ComboLinkSerializer(many=True) class Meta: model = Combo fields = ['user', 'id', 'created', 'links']
两种方案最终返回效果完全一致,无特殊扩展需求时优先选择方案1,减少冗余代码。
内容的提问来源于stack exchange,提问作者euh

