Django REST: Serializer lookup by UUID

Issue

I’m creating this simple shopping API in Django REST.

Internally I’m using IDs for foreign key constraints, while guuids are brought to the outside world.

For the checkout procedure, the user provides a list of article IDs he is willing to purchase. The object in the POST data thus looks as follows:

{
  assets: [
    {
       'product': 'd9d5044d-2284-4d15-aa76-2eee3675035b',
       'amount': 4
    },
    ....
  ]
}

I’m using the following ticket/asset models:

# Ticket
class Ticket(models.Model):
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='tickets', on_delete=models.CASCADE)


# Assets
class Asset(models.Model):
    ticket = models.ForeignKey(Ticket, related_name='assets', on_delete=models.CASCADE)
    stock_item = models.ForeignKey(Stock, related_name='stock_item', on_delete=models.SET_NULL, null=True)
    amount = models.IntegerField(validators=[MinValueValidator(0)])

And the serializers look as follows:

# Asset serializer
class AssetSerializer(serializers.ModelSerializer):

    class Meta:
        model = Asset
        fields = ('stock_item', 'amount')


# Ticket serializer
class TicketSerializer(WritableNestedModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    assets = AssetSerializer(many=True)

    class Meta:
        model = Ticket
        fields = ('uuid', 'owner', 'assets', )

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

When posting an object of the type specified above, the following error is presented:

{"assets":[{"stock_item": ["Invalid type. Expected PK, received string"]}]}

Which I can’t seem to solve, how do I instruct the serializer to use the uuid as the lookup value? I solved a similar problem on view-level earlier by using the lookup_field member, but that doesn’t seem to solve it. Any suggestions?
Enter code here

Solution

If I have understood you correctly, a SlugRelatedField should be able to find the correct related object.

class AssetSerializer(serializers.ModelSerializer):
    ticket = serializers.SlugRelatedField(
        read_only=True,
        slug_field='uuid',
        queryset=Ticket.objects.all() # Might be redundant with read_only=True
    )

    class Meta:
        model = Asset
        fields = ('ticket', 'stock_item', 'amount')

Answered By – Johan

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published