[英]How to retrieve a many-to-many field with backward relationships lookup in Django REST Framework serializer?
Please correct my title if it's not correct.如果标题不正确,请更正我的标题。 My problem is I want to retrieve
FinishType
's name
from Product
.我的问题是我想从
Product
检索FinishType
的name
。 I have tried 2 ways to achieve this: first attempt and second attempt .我尝试了两种方法来实现这一目标:第一次尝试和第二次尝试。
My simplifed related models in models.py
:我在
models.py
简化的相关模型:
class Product(models.Model):
product_id = models.CharField(max_length=6)
color = models.ForeignKey(ColorParent, on_delete=models.SET_NULL, null=True)
collection = models.ForeignKey(ProductCollection, on_delete=models.SET_NULL, null=True)
@property
def get_distributors(self):
return Distributor.objects.filter(distributor__products=self).count()
def __str__(self):
return self.product_id
class FinishType(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class ProductFinishType(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
market = models.ForeignKey(Market, on_delete=models.CASCADE)
finish_types = models.ManyToManyField(FinishType)
def __str__(self):
return '%s - %s' % (self.product, self.market)
class ProductAlias(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
market = models.ForeignKey(Market, on_delete=models.CASCADE)
name = models.CharField(max_length=50, null=True, blank=True)
def __str__(self):
return '%s - %s' % (self.product, self.name)
My serializers.py
:我的
serializers.py
:
class ProductGridSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField(source='get_name')
finishing = serializers.SerializerMethodField('get_finish_types')
distributor = serializers.ReadOnlyField(source='get_distributors')
@staticmethod
def get_name(obj):
return [pa.name for pa in obj.productalias_set.all()]
@staticmethod
def get_finish_types(obj):
return [pft.name for pft in obj.productfinishtype_set.all().select_related('finish_types')] # first attempt
class Meta:
model = Product
fields = ['id', 'product_id', 'name', 'collection', 'finishing', 'distributor']
First attempt works for name
field which fetches ProductAlias
's name
but gives me this error:第一次尝试的工程
name
,其获取场ProductAlias
的name
,但给我这个错误:
FieldError at /api/product_grids/
/api/product_grids/ 处的 FieldError
Invalid field name(s) given in select_related: 'finish_types'.select_related 中给出的字段名称无效:'finish_types'。 Choices are: product, market
选项是:产品、市场
My get_finish_types()
on second attempt:我的
get_finish_types()
第二次尝试:
@staticmethod
def get_finish_types(obj):
product_finish_types = obj.productfinishtype_set.all()
response = ProductFinishTypeSerializer(product_finish_types, many=True, source='finish_types').data
return response
It gives me the whole object datas:它给了我整个对象数据:
{
"id": 1,
"product_id": "BQ1111",
"name": [
"White Stone"
],
"collection": 1,
"finishing": [
{
"id": 1,
"product": 1,
"market": 1,
"finish_types": [
1,
3,
5
]
}
],
"distributor": 5
},
My desired output is something like:我想要的输出是这样的:
{
"id": 1,
"product_id": "BQ1111",
"name": [
"White Stone"
],
"collection": 1,
"finishing": [
"Polished",
"Carved",
"Melted"
],
"distributor": 5
},
Create a serializer for FinishType
,为
FinishType
创建一个序列化FinishType
,
class FinishTypeSerializer(serializers.ModelSerializer):
class Meta:
model = FinishType
fields = ('name',)
and wire-up it in ProductGridSerializer
using SerializerMethodField
并使用
SerializerMethodField
在ProductGridSerializer
连接它
class ProductGridSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField(source='get_name')
distributor = serializers.ReadOnlyField(source='get_distributors')
finishing = serializers.SerializerMethodField() def get_finishing(self, product): qs = FinishType.objects.filter(productfinishtype__product=product) return FinishTypeSerializer(qs, many=True).data
@staticmethod
def get_name(obj):
return [pa.name for pa in obj.productalias_set.all()]
class Meta:
model = Product
fields = ['id', 'product_id', 'name', 'collection', 'finishing', 'distributor']
Inspired by @Arakkal Abu's queryset, I tried it using my first attempt.受到@Arakkal Abu 的查询集的启发,我第一次尝试使用它。
FinishTypeSerializer
added in serializers.py
:在
serializers.py
添加了FinishTypeSerializer
:
class FinishTypeSerializer(serializers.ModelSerializer):
class Meta:
model = FinishType
fields = ('name',)
ProductGridSerializer
in serializers.py
: serializers.py
ProductGridSerializer
:
class ProductGridSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField(source='get_name')
finishing = serializers.SerializerMethodField(source='get_finishing')
distributor = serializers.ReadOnlyField(source='get_distributors')
@staticmethod
def get_name(obj):
return [pa.name for pa in obj.productalias_set.all()]
@staticmethod
def get_finishing(product):
return [pft.name for pft in FinishType.objects.filter(productfinishtype__product=product)]
class Meta:
model = Product
fields = ['id', 'product_id', 'name', 'collection', 'finishing', 'distributor']
The JSON output is: JSON 输出为:
{
"id": 1,
"product_id": "BQ1111",
"name": [
"White Stone"
],
"collection": 1,
"finishing": [
"Polished",
"Honed",
"Carved"
],
"distributor": 5
},
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.