Django REST - Обновление или создание объекта с помощью ссылки на внешний ключ
Document
- родительская модель, а LineItem
- дочерняя модель с внешней ключевой ссылкой на Document
Я могу удалять LineItem по отдельности. Однако я не могу создать или обновить отдельный LineItem, поскольку постоянно получаю ValidationError
, говорящий 'document': [ErrorDetail(string='This field is required.', code='required')
Я нашел несколько обходных путей, но мне интересно, есть ли более стандартный способ решения этой проблемы, который я, возможно, упускаю из виду
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)
Итак, метод destroy работает нормально, как и ожидалось, но метод update выкидывает ошибку, как указано выше.
Если я модифицирую класс Serializer, чтобы явно установить поле document
, он работает. Однако мне кажется, что должен быть лучший способ обновления полей Foreign Key.
Аналогично, метод create также не работает, а если я модифицирую класс Serializer, чтобы явно установить document_id из URL запроса, то он работает.
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__'