DRF 的 HyperLinkedRelatedField 非常好用,但请求 Json 格式的数据的时候,还要在根据返回的 url 字段再请求一遍,所以有了个想根据请求头确定返回数据类型的想法
class BaseSerializer(serializers.HyperlinkedModelSerializer):
def __new__(cls, *args, **kwargs):
media_field = kwargs["context"]["request"].accepted_media_type
if hasattr(cls, "related_fields"):
for name, fields in cls.related_fields.items():
if "text" in media_field:
field = fields.get("text", None)
elif "json" in media_field:
field = fields.get("json", None)
elif "yaml" in media_field:
field = fields.get("yaml", None)
else:
log.error(f"{name} not found any type field")
continue
cls._declared_fields[name] = field
cls.Meta.fields += (name,)
return super().__new__(cls, *args, **kwargs)
根据请求头里包含的 accepted_media_type 来判断
使用方法
class PermissionSerializer(BaseSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='permission-detail',
lookup_field="codename",
# lookup_url_kwarg="codename",
)
name = serializers.CharField(max_length=255)
codename = serializers.CharField(max_length=100)
content_type = serializers.SlugRelatedField(
read_only=True,
slug_field="app_label"
)
related_fields = dict(
user_set=dict(
text=serializers.HyperlinkedRelatedField(
view_name='user-detail', many=True,
queryset=User.objects.get_queryset(),
lookup_field="username",
required=False,
),
json=serializers.StringRelatedField(many=True),
yaml=serializers.StringRelatedField(many=True),
),
group_set=dict(
text=serializers.HyperlinkedRelatedField(
view_name='group-detail', many=True,
queryset=Group.objects.get_queryset(),
lookup_field="name",
required=False, ),
json=serializers.StringRelatedField(many=True),
yaml=serializers.StringRelatedField(many=True),
),
)
class Meta:
model = Permission
fields = (
'name', 'codename', 'content_type', 'url'
)
测试可行,还有其他好用的方法吗?
或者说我这个方法符合 REST 的风格吗?