Django REST - Updating or Creating object with foreign key reference

Document is the parent Model and LineItem is the child model with a foreign key reference to Document

I am able to delete LineItem individually. However, I am unable to create or update individual LineItem as I keep getting a ValidationError stating 'document': [ErrorDetail(string='This field is required.', code='required')

I have found a few workarounds but am wondering if there is a more standard way to solve this that I maybe overlooking

class Document(models.Model):
    """
    ORM representing Document object
    """
    id = models.AutoField(
        primary_key=True,
    )
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='documents',
    )

class LineItem(models.Model):
    """
    ORM representing line items in a document.
    """

    id = models.AutoField(
        primary_key=True,
    )
    document = models.ForeignKey(
        Document,
        on_delete=models.CASCADE,
        related_name='line_items',
    )
    description = models.CharField(
        max_length=50,
        blank=True,
        db_default='',
        default='',
    )
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='line_items',
    )

serializers.py

class LineItemSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = LineItem
        fields = '__all__'

urls.py

 # Add a document line item
    path('api/document/<int:doc_pk>/line/', DocumentLineItemCreateAPI.as_view(), name='document-line-item-add-api'),

    # Edit a document line item
    path('api/document/<int:doc_pk>/line/<int:pk>/', DocumentLineItemUpdateAPI.as_view(), name='document-line-item-update-api'),

views.py

class DocumentLineItemUpdateAPI(generics.RetrieveUpdateDestroyAPIView):
    """
    Unified view for retreiving, updating or deleting document line items
    """
    serializer_class = LineItemSerializer

    def get_queryset(self):
        return LineItem.objects.all()
    
    def get_object(self):
        obj = get_object_or_404(self.get_queryset(), \
                                document_id=self.kwargs.get('doc_pk'), id=self.kwargs.get('pk'))
        return obj
    
    def destroy(self, request, doc_pk, pk, *args, **kwargs):
        return super().destroy(request, *args, **kwargs)
           
    def update(self, request, doc_pk, pk, *args, **kwargs):
        return super().update(request, doc_pk, pk, *args, **kwargs)
        

So, the destroy method works fine as expected but the update method throws the error as stated above.

If I modify the Serializer class to explicitly set the document field, it works. However I feel that there should be a better way to update Foreign Key fields. Similarly, the create method also fails and if I modify the Serializer class to explicitly set the document_id from request URL it works.

class LineItemSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    document = serializers.SerializerMethodField()

    def get_document(self, obj):
        doc_id = self.context.get('request').parser_context.get('kwargs').get('doc_pk')
        return Document.objects.get(pk=doc_id) 

    def create(self, validated_data):
        doc_id = self.context.get('request').parser_context.get('kwargs').get('doc_pk')
        validated_data['document_id'] = doc_id
        return super().create(validated_data)

    class Meta:
        model = LineItem
        fields = '__all__'
Back to Top