Question: My `Beta` model's stage field provides 5 choices. I want my serializer to not always accept all these choices but only some of them according to the serialized object's actual stage value. For example, if `my_beta_object.stage == 1`, then the serializer should expect (and offer) only stages 2 and 3, if `my_beta_object.stage == 2`, only stages 2 and 4, etc.

```py
# models.py
class Beta(models.Model):
    class BetaStage(models.IntegerChoices):
        REQUESTED = (1, "has been requested")
        ACCEPTED = (2, "has been accepted")
        REFUSED = (3, "has been refused")
        CORRECTED = (4, "has been corrected")
        COMPLETED = (5, "has been completed")

    stage = models.ChoiceField(choices=self.BetaStage.choices)

# serializers.py
class BetaActionSerializer(serializers.ModelSerializer):
    stage = serializers.ChoiceField(
        # choices=?
    )

    class Meta:
        model = Beta
        fields = ("stage",)

# views.py
class BetaViewSet(viewsets.ModelViewSet):
    serializer_class = BetaSerializer

    def get_serializer_class(self):
        if self.action == "update":
            return BetaActionSerializer
        return self.serializer_class

```

How can I dynamically limit the choices of that field according to the serialized object's field value?

Answer: 
You could try to override the `__init__` method of your serializer and then dynamically generates the choices. However, it's not as simple as `choices=my_generated_choices`. It's a bit more complicated, and there's an in-depth solution on [that topic over there](https://github.com/encode/django-rest-framework/issues/3383)

The alternative and simpler method is to use the `validate()` method, which is triggered at the end of the validation process, after each field has been validated successfully. You could do the following:

* Write a static dict that maps each status to its valid status choices
* In the `validate` method, if `updating`, check if the new status is a valid choice based on your current status, using your static dict
* If not, raise a `ValidationError`

```py
# Example of mapping. Might want to make it pretties and put it in the model itself
mapping = {
  1: [2, 3],
  2: [1, 3],
  # ...
}

# And in validate
def validate(self, data):
    # We're in an update scenario
    if self.instance not None: 
        # It doesnt appear to be required, so use .get()
        new_stage = data.get("stage")
        # Not sure if an instance can have no stage?
        if new_stage is not None and self.instance.stage is not None: 
            # Our check
            if new_stage not in mapping[self.instance.stage]:
                raise ValidationError("Invalid stage")

```
Part of the explanation and a start for a solution I found [here](https://github.com/encode/django-rest-framework/issues/2555#issuecomment-74242909).
By design, I cannot get the context at fields' initialization apparently. I need to redefine the ChoiceField choices attribute at **serializer**'s initialization.

```py
# serializers.py
class BetaActionSerializer(ModelSerializer):
    def __init__(self, *args, **kwargs):
        super(ModelSerializer, self).__init__(*args, **kwargs)
        if self.instance:
            if self.instance.stage == Beta.BetaStage.REQUESTED.value:
                self.fields["stage"].choices = [
                    (Beta.BetaStage.ACCEPTED, Beta.BetaStage.ACCEPTED.name),
                    (Beta.BetaStage.REFUSED, Beta.BetaStage..REFUSED.name),
                ]
            etc.

```

I'm not marking this answer as a solution because I'm the original poster and I'm not sure this is a solid or desirable solution. However I'm hopeful this could help someone with the same or a similar issue in the future, as I've struggled finding information myself.