在 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')
下面给出了代码以及当前输出和预期输出。有的话请帮忙,谢谢。
在 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')