嵌套序列化器为每个序列化器创建方法

问题描述 投票:0回答:1

我有一个 Club 模型和一个 Address 模型。

class Club(models.Model):
    name = models.CharField(max_length=100)
    owner = models.ForeignKey(UserAccount,on_delete=models.CASCADE,related_name = 'owner_of')
    ##members = models.ManyToManyField(UserAccount,related_name = 'member_of')
    ##staff = models.ManyToManyField(UserAccount,related_name = 'staff_of')
    def __str__(self):
        return f'{self.name}'

class Address(models.Model):
    name = models.CharField(max_length=100)
    street = models.CharField(max_length=150)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100, blank=True, null=True)  # Optional for countries without states
    province = models.CharField(max_length=100, blank=True, null=True)  # Optional for countries without provinces
    country = models.CharField(max_length=50)
    postal_code = models.CharField(max_length=20)

    club = models.ForeignKey(Club,on_delete=models.CASCADE,related_name = 'address')
    def __str__(self):
        return f'{self.name}'   

他们有受人尊敬的序列化者。

 class AddressSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Address
            fields = ['id', 'name', 'street', 'city', 'state', 'province', 'postal_code', 'country']
    
        def create(self,validated_data):
            user=self.context['user']
            club=Club.objects.get(owner=user)
            address=Address.objects.create(club=club,**validated_data)
            return address
    
    class ClubSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Club
            fields = ['id', 'name']
    
        def create(self,validated_data):
            user=self.context['user']
            club=Club.objects.create(owner=user,**validated_data)
            return club
    
    
    class ClubRegistrationSerializer(serializers.Serializer):
    
    
       
        address= AddressSerializer2()
        club=ClubSerializer2()
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # We pass the "upper serializer" context to the "nested one"
            self.fields['address'].context.update(self.context)
            self.fields['club'].context.update(self.context)

这是我发布的数据

{
 "club":{"name":"someclub"},
 "address":{
   "name":"Bodrum Location",
   "street":"140",
    "city":"bodrum",
    "state":"california",
    "province":"some provence",
    "postal_code":"123",
    "country":"USA"
    }
}

我可以轻松实现我的视图的创建方法并且

这样做:

@action(detail=False,methods=['post'])
def register(self, request):
    serializer = ClubRegistrationSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    club_data=serializer.validated_data.pop("club")
    address_data=serializer.validated_data.pop("address")
    club=Club.objects.create(owner=self.request.user,**club_data) 
    address=Address.objects.create(club=club,**address_data)
    response={}
    response['address']=AddressSerializer(address).data
    response['club']=ClubSerializer(club).data
    return Response(response, status=status.HTTP_201_CREATED)
  1. 但是从我读到的内容来看,在视图中而不是在序列化器中执行逻辑并不理想。 因此,我可以将创建方法从视图的创建移动到序列化器的创建。 但对我来说没有意义的是我无法调用嵌套序列化器的 create 方法。实际上,我什至无法获取嵌套的序列化器对象,因此我可以调用它的 create 方法。您可以将其视为正在遍历一棵树并调用每个序列化器的创建方法,如果它们已创建,则调用其子级。

理想情况下,我不应该实现 ClubRegistrationSerializer 的 create 方法中的所有逻辑。 每个序列化器都应该对自己的序列化器负责。

我应该能够调用 ClubRegistrationSerializer 的 create 方法,并且应该调用 Address 和 Club 序列化器的 create 方法。

我看到的每个示例都处理父序列化器的创建中的所有逻辑。

  1. 其次,如何使用地址 obj 和 Club obj 调用 ClubRegistrationSerializer 并获取数据并将其发送给用户,以便响应具有 ID。

我已经尝试过

ClubRegistrationSerializer(address=addressOBJ,club=clubOBJ)
像这样 但这引发了异常。 目前我正在创建一个字典并附加模型的值。

这是我想从序列化器获得的响应。

{"club":{"name":"someclub","id":"1"},
 "address":{
   "id":"1",
   "name":"Some Location",
   "street":"140",
    "city":"San Fran",
    "state":"california",
    "province":"some province",
    "postal_code":"123",
    "country":"USA"
    }
}
django django-rest-framework django-views django-serializer
1个回答
0
投票

你需要像关系网一样考虑实施。

首先,您可以将

club = models.ForeignKey
字段重构为 OneToOne 关系字段。 然后,您可以摆脱有效负载中的主要字典包装器,并将俱乐部字段平面和地址字段实现为字典。

序列化器

.create
方法仅通过
Model.objects.create
方法在后台创建新实例,因此您不需要真正调用该 serializers.create 方法。字段验证在序列化器中是最重要的 - 他们专门从事这项工作(专业代码中的逻辑至少应该委托给 services.py 文件)。但为了简单起见,让我们留在序列化器中的逻辑。

class ClubSerializer(serializers.ModelSerializer):
    address = AddressSerializer()

    class Meta:
        model = Club
        fields = ['id', 'name', 'address']

    def create(self, validated_data):
        address_data = validated_data.pop("address")
        instance = super().create(validated_data)
        instance.address = Address.objects.create(club=instance, **address_data)
        return instance

查看动作

    @action(detail=False,methods=['post'])
    def register(self, request):
        serializer = ClubSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)
© www.soinside.com 2019 - 2024. All rights reserved.