Django Rest Framework:序列化模型并通过外键对其他数据进行分组

时间:2022-09-27 20:51:12

I have the following three models:

我有以下三种型号:

class Package(models.Model):
  name = models.CharField()

class Part(models.Model):
  name = models.CharField()
  sku = models.IntegerField()

class Member(models.Model):
  name = models.CharField()

class MemberPurchase(models.Model):
  member = models.ForeignKey(Member)
  package = model.ForeignKey(Package)
  part = models.ForeignKey(Part)
  purchase_date = models.DateField()

I want to serialize MemberPurchase model for an API so that I can have all the information I need as below:

我想序列化一个API的MemberPurchase模型,以便我可以获得我需要的所有信息,如下所示:

{
  "name": "John Doe",
  "id": 123,
  "purchases": [
     {
       "name": "Package Silver",
       "parts": [
          {
            "name": "Part Silver 1",
            "sku": "12345",
          },
          {
            "name": "Part Silver 2",
            "sku": "145678",
          }
       ]
     },
     {
       "name": "Package Gold",
       "parts": [
           {
            "name": "Part Gold 1",
            "sku": "1010101",
          }
       ]
     }
  ]
}

I am not exactly sure how to build the serializer to give me the result above. I can write a serializer that will serialize a queryset from MemberPurchase but that will have a lot of repeated data.

我不完全确定如何构建序列化器来给我上面的结果。我可以编写一个序列化程序,它将从MemberPurchase序列化一个查询集,但是会有很多重复的数据。

I am guessing this needs multiple serializers:

我猜这需要多个序列化器:

class MemberSerializer(serializers.ModelSerilaizer):
  purchases = MemberPurchaseSerializer(source='memberpurchase_set', many=True)
  class Meta:
    model = Member
    fields = ['name', 'id']

class MemberPurchaseSerializer(serializers.Serializer):
  name = serializers.SerializerMethodField('get_package_name')
  parts = PackagePartSerializer(many=True)
  def get_pacakage_name(self, instance):
    return instance.package.name

class PackagePartSerializer(serializers.Serializer):
  name = serializers.SerializerMethodField('get_part_name')
  sku = serializers.SerializerMethodField('get_part_sku')
  def get_part_name(self, instance):
    return instance.part.name
  def get_part_sku(self, instance):
    return instance.part.sku

I don't think the above will produce what I need. Is there a better way to do this and get the results above?

我不认为上面会产生我需要的东西。有没有更好的方法来做到这一点并得到上面的结果?

Edit: So I decided to take this path but not sure if this is the most efficient implementation:

编辑:所以我决定采用这条路径,但不确定这是否是最有效的实现:

class PackagePartSerializer(serializers.Serializer):
   name = serializers.SerializerMethodField('get_part_name')
   sku = serializers.SerializerMethodField('get_part_sku')
   def get_part_name(self, instance):
     return instance.part.name
   def get_part_sku(self, instance):
     return instance.part.sku

class MemberSerializer(serializers.ModelSerilaizer):
  purchases = serializers.SerializerMethodField('get_member_purchases')

  def get_member_purchases(self, instance):
    mem_purchases = instance.memberpurchase_set.all()
    purchases = []
    for pur in mem_purchases:
      purchases.append({
        "name": pur.package.name,
        "id": pur.package.id,
        "parts": PackagePartSerializer(instance.memberpurchase_set.all(), many=True).data
      })
    return purchases

  class Meta:
     model = Member
     fields = ['name', 'id', 'purchases']

1 个解决方案

#1


0  

I am providing the solution I got to as an answer.

我提供的解决方案作为答案。

class PackagePartSerializer(serializers.Serializer):
   name = serializers.SerializerMethodField('get_part_name')
   sku = serializers.SerializerMethodField('get_part_sku')
   def get_part_name(self, instance):
     return instance.part.name
   def get_part_sku(self, instance):
     return instance.part.sku

class MemberSerializer(serializers.ModelSerilaizer):
  purchases = serializers.SerializerMethodField('get_member_purchases')

  def get_member_purchases(self, instance):
    mem_purchases = instance.memberpurchase_set.all()
    purchases = []
    for pur in mem_purchases:
      purchases.append({
        "name": pur.package.name,
        "id": pur.package.id,
        "parts": PackagePartSerializer(instance.memberpurchase_set.all(), many=True).data
      })
    return purchases

  class Meta:
     model = Member
     fields = ['name', 'id', 'purchases']

#1


0  

I am providing the solution I got to as an answer.

我提供的解决方案作为答案。

class PackagePartSerializer(serializers.Serializer):
   name = serializers.SerializerMethodField('get_part_name')
   sku = serializers.SerializerMethodField('get_part_sku')
   def get_part_name(self, instance):
     return instance.part.name
   def get_part_sku(self, instance):
     return instance.part.sku

class MemberSerializer(serializers.ModelSerilaizer):
  purchases = serializers.SerializerMethodField('get_member_purchases')

  def get_member_purchases(self, instance):
    mem_purchases = instance.memberpurchase_set.all()
    purchases = []
    for pur in mem_purchases:
      purchases.append({
        "name": pur.package.name,
        "id": pur.package.id,
        "parts": PackagePartSerializer(instance.memberpurchase_set.all(), many=True).data
      })
    return purchases

  class Meta:
     model = Member
     fields = ['name', 'id', 'purchases']