我如何使用POSTMAN发送Django-Rest-Framework中的项目名称而不是PK?

vjrehmav  于 2022-11-07  发布在  Postman
关注(0)|答案(2)|浏览(192)

因此,我正在使用Django Rest框架创建一个电子商务API,并且我一直在尝试发送Item的名称而不是Item的PK来创建订单。
以下是我正在使用的模型:
第一个
这是我用来创建订单的序列化程序:

class PlacedOrderSerializer(serializers.ModelSerializer):
    ordered_by = serializers.ReadOnlyField(source="ordered_by.email")

    class Meta:
        model = PlacedOrder
        fields = (
            "id",
            "created_at",
            "ordered_by",
            "first_name",
            "last_name",
            "phone",
            "address",
            "zipcode",
            "items",
            "total_price",
        )

下面是我用来创建订单的视图:

class CreateOrder(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticated]

    queryset = PlacedOrder.objects.all()
    serializer_class = PlacedOrderSerializer

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

这是我在《 Postman 》中的投入:

{
    "first_name": "yes",
    "last_name": "no",
    "phone": "0100000000",
    "address": "whatever address",
    "zipcode": "254",
    "items": [
            1,
            1,
            2
        ],

    "total_price": "69"
}

这是输出:

{
    "id": 13,
    "created_at": "2022-10-26T20:56:08.789574Z",
    "ordered_by": "bal@bal.com",
    "first_name": "yes",
    "last_name": "no",
    "phone": "0100000000",
    "address": "whatever address",
    "zipcode": "254",
    "items": [
        1,
        2
    ],
    "total_price": 69
}

我基本上想让它在输入中取项目的名称和数量,而不是产品的PK。
我试过使用RelatedField,但这使得“项目”在没有任何产品的情况下返回到后端,并生成一个空白订单。

ffx8fchx

ffx8fchx1#

请尝试以下方法:

class PlacedOrderSerializer(serializers.ModelSerializer):

    # HERE
    ordered_by = serializers.StringRelatedField(many=True, read_only=True)

    class Meta:
        model = PlacedOrder
        fields = (
            "id",
            "created_at",
            "ordered_by",
            "first_name",
            "last_name",
            "phone",
            "address",
            "zipcode",
            "items",
            "total_price",
        )

但请确保将self.name添加到模型__str__中。

sdnqo3pr

sdnqo3pr2#

You need to use a SlugRelatedField [DRF-doc] here, like:
class PlacedOrderSerializer(serializers.ModelSerializer):
    ordered_by = serializers.ReadOnlyField(source="ordered_by.email")
    items = serializers.SlugRelatedField(
        many=True,
        slug_field='name',
        queryset=Product.objects
    )

    class Meta:
        model = PlacedOrder
        fields = (
            # ...
        )
This will thus make the serializer interpret the name fields, and query the Product objects with that name, and add these to the many-to-many relation.
Note that this will result in a query for each item, so if the list of items can be long, you might want to consider a different strategy, like serializing a list of product PKs, and then in the view construct a mapping name -> product, and use that to construct the many-to-many relation.

Note: It is normally better to use a slug field (a short identifier), than a name field for these kinds of relations. Slugs are meant to be database friendly (only contain ascii characters, no spaces, etc), and furthermore slugs normally do not change, whilst a name can. So if you later rename a Product, then the order will no longer point to the correct product.

相关问题