在 DRF 中,我如何序列化相关模型(OneToOne)并显示数据而不是列表数据类型,而是单值实例?

In DRF how do I serialize a related model(OneToOne) and display the data not in a list data type but single value instance?

下面给出了代码以及当前输出和预期输出。有的话请帮忙,谢谢。 在 ProductPriceMapping table 中,ProductDetail table 和 PriceList 与 OneToOne 关系相关,但是当使用 related_name= 参数获取 Price 数据时,一个产品必须有一个值,但是正在显示的数据是列表数据类型。

##models.py


class PriceList(models.Model):
    priceCode = models.BigAutoField(primary_key= True)
    maxRetailPrice= models.FloatField(max_length=20)
    baseDiscount = models.FloatField(max_length=20, default=0)
    seasonalDiscount = models.FloatField(max_length=20, default=0)

    def __str__(self):
        return '%s'% (self.maxRetailPrice)

class ProductDetail(models.Model):
    productCode = models.BigAutoField(primary_key=True)
    productName = models.CharField(max_length=100)
    manufacturer = models.CharField(max_length=100)

    def __str__(self):
        return self.productName

class ProductPriceMapping(models.Model):
    productPriceCode= models.BigAutoField(primary_key=True)
    productCode= models.ForeignKey(ProductDetail,on_delete=models.CASCADE,related_name='price')
    priceCode= models.OneToOneField(PriceList,on_delete=models.CASCADE)

    def __str__(self):
        return '%s' % (self.priceCode)

##serializers.py

from .models import CategoryDetail, EmployeeDetail, ProductCategoryMapping, ProductPriceMapping, SalaryDetail, ProductDetail, PriceList

class ProductPriceListSerializer(serializers.ModelSerializer):
    class Meta:
        model = PriceList
        fields = ('priceCode','maxRetailPrice',
                  'baseDiscount', 'seasonalDiscount')

class ProductPriceMappingSerializer(serializers.ModelSerializer):
    class Meta:
        model= ProductPriceMapping
        fields= ('productPriceCode','productCode', 'priceCode')

class ProductDetailsSerializer(serializers.ModelSerializer):
    category= serializers.StringRelatedField(many= True, read_only= True)
    price = serializers.StringRelatedField( many= True, read_only= True)
    class Meta:
        model = ProductDetail
        fields = ('productCode', 'productName', 'manufacturer','category', 'price')



API 的外观:


[
    {
        "productCode": 1,
        "productName": "NeoChef",
        "manufacturer": "LG",
        "category": [
            "1: Microwave Oven"
        ],
        "price": [
            "26000.0"  ##expected the price value not be in a list
        ]
    },
    {
        "productCode": 2,
        "productName": "The Frame",
        "manufacturer": "Samsung",
        "category": [
            "2: Television"
        ],
        "price": [
            "120000.0" ##expected the price value not be in a list
        ]
    },
    {
        "productCode": 3,
        "productName": "Galaxy S22+",
        "manufacturer": "Samsung",
        "category": [
            "3: Smart Phone"
        ],
        "price": [
            "79000.0" ##expected the price value not be in a list
        ]
    }
]

#预期

[
    {
        "productCode": 1,
        "productName": "NeoChef",
        "manufacturer": "LG",
        "category": [
            "1: Microwave Oven"
        ],
        "price": "26000.0"  
    }
]```

在您的情况下,price 字段不是 one-to-one 相关字段,您需要将 productCode 更改为 OneToOneField,或者如果您不这样做想要更改数据库字段,只需使用 SerializerMethodField 即可获得相同的结果。在第一种情况下,从序列化程序字段中删除 many=True 参数应该会有所帮助。在第二种情况下,SerializerMethodField 将帮助您进行自定义表示,例如:

class ProductDetailsSerializer(serializers.ModelSerializer):
    category= serializers.StringRelatedField(many=True, read_only=True)
    price = serializers.SerializerMethodField()

    class Meta:
        model = ProductDetail
        fields = ('productCode', 'productName', 'manufacturer','category', 'price')

    def get_price(self, obj):
        # If it's guaranteed that there will be only one related object, or retrieve the needed object depending on your demands
        return str(obj.price.first())

一种简单的方法是使用 MethodField...

class ProductPriceMappingSerializer(serializers.ModelSerializer):
    priceCode = serializers.SerializerMethodField()

    class Meta:
        model= ProductPriceMapping
        fields= ('productPriceCode','productCode', 'priceCode')
    
    @staticmethod
    def get_priceCode(obj):
        return obj.priceCode.maxRetailPrice  # or any other fields that you like to show in your response

但如果您想显示基于其他序列化程序的所有 priceList 字段,您可以执行以下操作:

class ProductPriceMappingSerializer(serializers.ModelSerializer):
    priceCode = ProductPriceListSerializer()

    class Meta:
        model= ProductPriceMapping
        fields= ('productPriceCode','productCode', 'priceCode')

谢谢各位,我是这样解决的:

models.py

class ProductPriceMapping(models.Model):
    productPriceCode= models.BigAutoField(primary_key=True)
    productCode= models.OneToOneField(ProductDetail,on_delete=models.CASCADE,related_name='price')
    priceCode= models.ForeignKey(PriceList,on_delete=models.CASCADE)

    def __str__(self):
        return '%s' % (self.priceCode)

serializers.py

class ProductDetailsSerializer(serializers.ModelSerializer):
    category= serializers.StringRelatedField(many= True, read_only= True)
    price = serializers.StringRelatedField(read_only= True)
    class Meta:
        model = ProductDetail
        fields = ('productCode', 'productName', 'manufacturer','category', 'price')