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__'