Getting instance values during validate()

Hello,

I’m a relative Django n00b so apologies if this is a novice question.

I have 2 entities:

  • EntityOne
  • EntityTwo, which has a OneToOneField mapping with EntityOne

My view has a put() method for updates:

class MyView(...):
    def put(self, request, *args, **kwargs):
        serializer = EntityOneUpdateRequestSerializer(instance, request.data)

        if serializer.is_valid():
            ...

The first serializer is as follows:

class EntityOneUpdateRequestSerializer(...):
    class Meta:
        fields = ("entity_one",)

    entity_one = EntityOneUpdateSerializer()

The second (nested) serializer is as follows:

class EntityOneUpdateSerializer(...):
    class Meta:
        model = models.EntityOne
        fields = (
            ...
            "entity_two",
            ...
        )

    entity_two = EntityTwoUpdateSerializer(...)

EntityTwoUpdateSerializer has a validate() method where I need to compare the values of EntityTwo that have changed with the current instance - the current one in the database.

class EntityTwoUpdateSerializer(...):
    model = models.EntityTwo

    def validate(self, data):
       ...

How do I get the current instance to compare against the proposed changed values? I’ve tried referencing self.instance in the validate() method, only to find that it is not supplied when the function is called.

I’ve also tried using the context = {} keyword but when I get to the definition of the EntityTwoUpdateSerializer in EntityOneUpdateSerializer, I do not have a self object that I can get it from.

Many thanks in advance for any assistance.

@CodenameTim - You still around to handle DRF-related questions?

Can you clarify which of these serializers are ModelSerializers and which aren’t?

Thank you - they are all DRF serializers, from rest_framework.

That one uses the Meta.model property which is specific to a ModelSerializer no?

Hmm that may be slightly confusing. Can you share your full serializers and view? Can you also annotate it with where you tried specific things and what it resulted in via comments? You said you tried accessing self.instance, but it’s not clear where. Or how that code was used.

I know DRF is a bit weird about nested serializers. There’s a package that tries to make it easier, GitHub - beda-software/drf-writable-nested: Writable nested model serializer for Django REST Framework

Hello,

Thanks to all for their responses.

I believe this is fixed now.

I had to add an id into the context object in the View, which was automatically propagated to all the Serializers, including the nested ones. Then I could extract the id from the context in the Serializer and use it to get the pre-update version of the object from the database for comparison purposes.

class MyView(...):
    def put(self, request, *args, **kwargs):
        # Add id to context.
        serializer = serializers.EntityOneUpdateRequestSerializer(
            instance=instance,
            data=request.data,
            context={"user_id": self.request.user.id},
        )

… and…

class EntityTwoUpdateSerializer(...):
    model = models.EntityTwo

    def validate(self, data):
        context = getattr(self, "context", None)

        if context is None:
            return data

        # Get id from context.
        user_id = context.get("user_id")

        # Get object from database.
        entity_two = models.EntityTwo.objects.get(user_id=user_id)

        ... do validation...

        return data