- 我想听听您的意见,这种方法正确吗?
- 如何更好地序列化 m2m 中间模型?
- 我想知道如何组合
Display
和Create
序列化器。 models.py
class Material(models.Model):
name = models.CharField(max_length=120)
class Product(models.Model):
name = models.CharField(max_length=120)
materials = models.ManyToManyField(Material, through='MaterialProduct')
class MaterialProduct(models.Model):
material = models.ForeignKey(Material, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
rate = models.FloatField(default=100)
views.py
class Products(APIView):
def get(self, request, format=None):
products = Product.objects.all()
serializer = ProductDisplaySerializer(products, many=True) # Display
return Response(serializer.data)
def post(self, request, format=None):
serializer = ProductCreateSerializer(data=request.data) # Create
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializers.py
class MaterialSerializer(serializers.ModelSerializer):
class Meta:
model = Material
fields = '__all__'
class ProductMaterialRateSerializer(serializers.ModelSerializer):
material = MaterialSerializer(read_only=True)
material_id = serializers.PrimaryKeyRelatedField(
write_only=True, source='material', queryset=Material.objects.all())
class Meta:
model = MaterialProduct # attention!!!
fields = ('material', 'material_id', 'rate')
class ProductCreateSerializer(serializers.ModelSerializer):
'''To create a product with existed material and a material rate(extra field) '''
materials = ProductMaterialRateSerializer(many=True)
class Meta:
model = Product
fields = ('id', 'name', 'materials')
def create(self, validated_data):
materials_data = validated_data.pop('materials')
product = Product.objects.create(**validated_data)
for material_data in materials_data:
MaterialProduct.objects.create(
product=product,
material=material_data.get('material'),
rate=material_data.get('rate'))
return product
- 显示的数据:
{
"id": 29,
"name": "product 4",
"materials": [
{
"material_id": 3,
"rate": 30
},
{
"material_id": 2,
"rate": 70
}
]
}
创建要发送的数据:
{
"name" : "product 4",
"materials" : [
{
"material_id":3,
"rate" : 30
}
,{
"material_id":2,
"rate" : 70
}
]
}
创建后返回的数据:
- 注意:它正确保存了数据,但不显示如下!
{
"id": 29,
"name": "product 4",
"materials": [
{},
{}
]
}
最佳答案
您可以使用RetrieveAPIView
用于显示和 CreateAPIView
for create 是内置功能,可以使事情变得更简单,并且其他开发人员可以更轻松地使用您的代码,因为他们需要熟悉的是 DRF 的工作方式,而不是您编写代码的方式。基本上最好遵循其他开发人员熟悉的模式。
我不建议组合创建和显示序列化器,除非它们非常简单。如果它们变得有点复杂,那么调试或进行更改可能会变得困难,特别是当其他人正在调试您的代码时!
对于序列化 m2m,materials = ProductMaterialRateSerializer(many=True)
是正确的方法,为了创建,您可以使用内置功能,但如果它很复杂并且需要一些计算,那么我建议覆盖 save
和update
创建序列化程序中的方法。
对于返回的数据:
您可以像这样覆盖上下文:
def post(self, request, format=None):
serializer = ProductCreateSerializer(data=request.data) # Create
if serializer.is_valid():
# Get the saved object
saved_obj = serializer.save()
# Serialize the saved object with the preferred serializer.
response_data = ProductDisplaySerializer(saved_obj).data
return Response(response_data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
关于python - Django Rest框架中多对多中间模型的实现方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55278053/