Python 如何在Django REST Framework序列化程序中使用向后关系查找检索多对多字段?
如果标题不正确,请更正。我的问题是我想从Python 如何在Django REST Framework序列化程序中使用向后关系查找检索多对多字段?,python,django,django-rest-framework,Python,Django,Django Rest Framework,如果标题不正确,请更正。我的问题是我想从产品中检索FinishType的名称。我尝试了两种方法来实现这一点:和。 我在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
产品
中检索FinishType
的名称
。我尝试了两种方法来实现这一点:和。我在
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)
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']
Myserializers.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)
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']
第一次尝试适用于name
字段,该字段获取ProductAlias
的name
,但出现以下错误:
/api/product_grids/select_related:“finish_types”中给出的字段名无效。选择是:产品,市场 我的
get\u finish\u 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
它提供了整个对象数据:
{
"id": 1,
"product_id": "BQ1111",
"name": [
"White Stone"
],
"collection": 1,
"finishing": [
{
"id": 1,
"product": 1,
"market": 1,
"finish_types": [
1,
3,
5
]
}
],
"distributor": 5
},
我想要的输出是这样的:
{
"id": 1,
"product_id": "BQ1111",
"name": [
"White Stone"
],
"collection": 1,
"finishing": [
"Polished",
"Carved",
"Melted"
],
"distributor": 5
},
为FinishType创建序列化程序
class FinishTypeSerializer(serializers.ModelSerializer):
class Meta:
model = FinishType
fields = ('name',)
并使用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']
类ProductGridSerializer(serializers.ModelSerializer):
name=serializers.SerializerMethodField(source='get\u name')
distributor=serializers.ReadOnlyField(source='get\u distributors')
finishing=serializers.SerializerMethodField()
def get_整理(自身、产品):
qs=FinishType.objects.filter(productfinishtype\uu product=product)
返回FinishTypeSerializer(qs,many=True)
@静力学方法
def get_名称(obj):
返回[obj.productalias_set.all()中pa的pa.name]
类元:
型号=产品
字段=['id'、'product\u id'、'name'、'collection'、'finishing'、'distributor']
为FinishType
创建序列化程序
class FinishTypeSerializer(serializers.ModelSerializer):
class Meta:
model = FinishType
fields = ('name',)
并使用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']
类ProductGridSerializer(serializers.ModelSerializer):
name=serializers.SerializerMethodField(source='get\u name')
distributor=serializers.ReadOnlyField(source='get\u distributors')
finishing=serializers.SerializerMethodField()
def get_整理(自身、产品):
qs=FinishType.objects.filter(productfinishtype\uu product=product)
返回FinishTypeSerializer(qs,many=True)
@静力学方法
def get_名称(obj):
返回[obj.productalias_set.all()中pa的pa.name]
类元:
型号=产品
fields=['id'、'product_id'、'name'、'collection'、'finishing'、'distributor']
受@Arakkal Abu的queryset的启发,我第一次尝试了它。FinishTypeSerializer
添加到serializers.py
:
class FinishTypeSerializer(serializers.ModelSerializer):
class Meta:
model = FinishType
fields = ('name',)
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']
serializers.py中的ProductGridSerializer
:
class FinishTypeSerializer(serializers.ModelSerializer):
class Meta:
model = FinishType
fields = ('name',)
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']
JSON输出为:
{
"id": 1,
"product_id": "BQ1111",
"name": [
"White Stone"
],
"collection": 1,
"finishing": [
"Polished",
"Honed",
"Carved"
],
"distributor": 5
},
受到@Arakkal Abu的queryset的启发,我第一次尝试了它。
FinishTypeSerializer
添加到serializers.py
:
class FinishTypeSerializer(serializers.ModelSerializer):
class Meta:
model = FinishType
fields = ('name',)
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']
serializers.py中的ProductGridSerializer
:
class FinishTypeSerializer(serializers.ModelSerializer):
class Meta:
model = FinishType
fields = ('name',)
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']
JSON输出为:
{
"id": 1,
"product_id": "BQ1111",
"name": [
"White Stone"
],
"collection": 1,
"finishing": [
"Polished",
"Honed",
"Carved"
],
"distributor": 5
},
非常感谢。我有很多类似的案例。您的解决方案也非常通用。SerializerMethodField肯定会有帮助。谢谢。我有很多类似的案例。您的解决方案也非常通用。SerializerMethodField确实有帮助。