Как использовать django rest framework для вложенного сериализатора - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть две модели User и Address.Модель адреса связана с моделью пользователя как OneToOneField.В моем случае я пытался обновить модель пользователя, в начальном случае поле адреса модели пользователя является нулевым.Итак, в первом случае, когда я обновляю модель пользователя, я хочу создать адрес.В остальных случаях нужно только обновить адрес.Как этого добиться?

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)

Мне нужно выйтикак показано ниже

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

В поле адреса содержится адрес объекта в качестве ответа.

Формат запроса данных

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>

1 Ответ

0 голосов
/ 01 февраля 2019

Вы можете использовать вложенный сериализатор и переопределить метод update:

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
...