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__'
Вернуться на верх