You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何临时将HyperlinkedRelatedField设为read_only?现有方法失效

Hey there! Let's figure out why your attempt to make a HyperlinkedRelatedField read-only isn't working, and fix it up.

The key thing here is that HyperlinkedRelatedField has specific initialization logic that makes simply toggling the read_only property after the serializer is created ineffective—unlike the auto-generated fields for model ForeignKeys, which are a bit more straightforward. Here are a couple of reliable ways to dynamically set it to read-only:

1. Dynamically modify the field in the serializer's __init__ method

This is the most common and robust approach. You can pass a custom flag when initializing the serializer, then adjust the field's read_only attribute during setup:

from rest_framework import serializers
from myapp.models import MyModel, RelatedModel

class MyModelSerializer(serializers.ModelSerializer):
    related_model = serializers.HyperlinkedRelatedField(
        view_name='relatedmodel-detail',
        queryset=RelatedModel.objects.all()
    )

    def __init__(self, *args, **kwargs):
        # Pull our custom flag from kwargs before calling the parent constructor
        make_related_read_only = kwargs.pop('make_related_read_only', False)
        super().__init__(*args, **kwargs)
        
        # Toggle the read-only state based on our flag
        if make_related_read_only:
            self.fields['related_model'].read_only = True

    class Meta:
        model = MyModel
        fields = ['id', 'name', 'related_model']

Then, when using the serializer (e.g., in a view), pass the flag to trigger the read-only setting:

# In a function-based view
serializer = MyModelSerializer(
    instance=my_model_instance,
    context={'request': request},
    make_related_read_only=True
)

# Or in a class-based view, override get_serializer to set the flag dynamically
class MyModelView(generics.RetrieveUpdateAPIView):
    serializer_class = MyModelSerializer
    queryset = MyModel.objects.all()

    def get_serializer(self, *args, **kwargs):
        # Example: Make it read-only for GET requests, writable for updates
        kwargs['make_related_read_only'] = self.request.method == 'GET'
        return super().get_serializer(*args, **kwargs)

2. Conditionally set read-only based on instance state

If you want to make the field read-only only during creation (or only during updates), you can check if the serializer has an existing instance:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    # Make the field read-only when creating a new object (no instance exists)
    if not self.instance:
        self.fields['related_model'].read_only = True

Why your initial attempt might have failed

Unlike the auto-generated PrimaryKeyRelatedField for model ForeignKeys, HyperlinkedRelatedField sets up its validation and deserialization logic during the serializer's initialization phase. If you tried to set read_only after the serializer was already created (e.g., in a view after initializing it), the field had already locked in its behavior, so the change didn't take effect. By modifying it in __init__, you adjust the field before any validation or serialization processes run.

内容的提问来源于stack exchange,提问作者Piotr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:46:58