简体   繁体   中英

How to use django rest framework nested serializer

I have two models User and Address. The Address model is connected to User model as OneToOneField. In my case I trying to update the User model, in Initial case the address field of User model is null. So in first case When I update User model, I want to create an Address. In other cases only need to update address. How to achieve this?

models.py

class User(AbstractUser):
    first_name = models.CharField(max_length=100, blank=True, default=None, null=True)
    dp = models.ImageField(upload_to='profiles/', blank=True)
    gender = models.CharField(choices=GENDER_TYPE_CHOICES, max_length=10, default=None, blank=True, null=True)
    marital_status = models.BooleanField(default=False)
    dob = models.DateField(default=None, blank=True, null=True, )
    email = models.EmailField(default=None, blank=True, null=True, unique=True)
    mobile = PhoneNumberField(blank=True, null=True, unique=True)
    fire_token = models.TextField(blank=True, default=None, null=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=True)

    def __str__(self):
        return str(self.first_name)


class Address(models.Model):
    user = models.OneToOneField(User, default=None, null=True, blank=True, related_name="address_user",
                                on_delete=models.CASCADE)
    raw = models.CharField(max_length=100, blank=True, default=None, null=True)
    street_number = models.CharField(max_length=100, blank=True, default=None, null=True)
    route = models.CharField(max_length=100, blank=True, default=None, null=True)
    locality = models.CharField(max_length=100, blank=True, default=None, null=True)
    postal_code = models.CharField(max_length=6, blank=True, default=None, null=True)
    state = models.CharField(max_length=100, blank=True, default=None, null=True)
    state_code = models.CharField(max_length=6, blank=True, default=None, null=True)
    country = models.CharField(max_length=100, blank=True, default=None, null=True)
    country_code = models.CharField(max_length=6, blank=True, default=None, null=True)

    def __str__(self):
        return str(self.raw)

serializers.py

  class AddressSerializer(ModelSerializer):
    class Meta:
      model = Address
      fields = '__all__'
  class UpdateUserProfileSerializer(ModelSerializer):
    class Meta:
      model = User
      fields = ('first_name', 'dp', 'gender', 'marital_status', 'dob', 'address')

views.py

class UserProfileAPIView(APIView):
    serializer_class = UserProfileSerializer
    permission_classes = [IsAuthenticated]

    # Get User Profile
    def get(self, request):
        serializer = UserProfileSerializer(request.user, context={'request': request})
        return Response({'result ': serializer.data},
                        status=status.HTTP_200_OK)


    def patch(self, request):

        user_serializer = UpdateUserProfileSerializer(request.user, data=request.data, context={'request': request})
        if user_serializer.is_valid():
            user_serializer.save()
            return Response({'response': 'Successfully updated', 'result': user_serializer.data},
                            status=status.HTTP_200_OK)
        else:
            return Response(user_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

I need out like below

{
    "result ": {
        "first_name": "Alwin Lazar V",
        "dp": null,
        "gender": null,
        "marital_status": false,
        "dob": null,
        "email": "alwinlazar46@gmail.com",
        "mobile": null,
        "address": null
    }
}

The address filed contain address object as response.

Request Data Format

first_name: Alwin
gender: m
marital_status: false
raw: <String>
street_number: <String>
route: <String> 
locality: <String>
postal_code: <String>
state: <String>
state_code: <String>
country: <String>
country_code: <String>

You can use the nested serializer and override the update method:

serializers.py

class AddressSerializer(ModelSerializer):

    class Meta:
       model = Address
       exclude = ('user',)


class UpdateUserProfileSerializer(ModelSerializer):
    address = AddressSerializer()

    class Meta:
        model = User
        fields = ('first_name', 'dp', 'gender', 'marital_status', 'dob', 'address')

   def update(self, instance, validated_data):
      address = validated_data.pop('address')
      instance = super().update(instance, validated_data)
      if hasattr(instance, 'address'):
         for key, value in address.items():
            setattr(instance.address, key, value)
         instance.address.save()
      else:
          Address.objects.create(user=instance, **address)
      return instance

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM