Как обновить значение в поле JSON в Django Rest Framework

Я делаю API с Django Rest Framework и у меня возникла проблема. Когда я пытаюсь изменить значение JSON-поля с False на True (или наоборот), это не изменяет значение конкретного ключа, но изменяет все JSON-поле на True (или False). Как мне изменить значение только одного ключа?

Мой models.py:

class Account(AbstractBaseUser):
    email = models.EmailField(verbose_name="email", unique=True, max_length=100)
    username = models.CharField(max_length=30, unique=True)
    date_joined = models.DateTimeField(verbose_name="date joined", auto_now_add=True)
    last_login = models.DateTimeField(verbose_name="last login", auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    fruit = models.JSONField(default={"Apple":False, "Pear": True, "Orange":False}) #This is that field

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["username"]

    objects = MyAccountManager()

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return self.is_admin

    def has_module_perms(self, app_label):
        return True

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

Мой serializers.py:

class FruitSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ["fruit"]

        def update(self, instance, validated_data): 
            instance.fruit = validated_data.get('fruit', instance.fruit)
            instance.save()
            return instance

Мой views.py:

class UpdateFruitView(generics.UpdateAPIView):
    queryset = Account.objects.all()
    serializer_class = FruitSerializer
    permission_classes = (IsAuthenticated,)

    def update(self, request, *args, **kwargs):
        fruit = request.data.get("fruit")
        select_fruit = request.user.fruit[fruit]
        if select_fruit == False:
            select_fruit = True
            data_to_change = {'fruit': select_fruit}
            serializer = self.serializer_class(request.user, data=data_to_change, partial=True)
            if serializer.is_valid():
                self.perform_update(serializer)

            return Response(serializer.data)

        if select_fruit == True:
            select_fruit = False
            data_to_change = {'fruit': select_fruit}
            serializer = self.serializer_class(request.user, data=data_to_change, partial=True)
            if serializer.is_valid():
                self.perform_update(serializer)

            return Response(serializer.data)

Как я хочу, чтобы поле JSON выглядело следующим образом:

  • до: {"Apple":False, "Pear": True, "Orange":False}
  • после того, как я отправил запрос на изменение Apple: {"Apple":True, "Pear": True, "Orange":False}

Вам, вероятно, следует пересмотреть структуру вашей базы данных, но есть решение для вашей проблемы:

В зависимости от того, что вы отправили для обновления поля fruit:

Вероятно, именно этим вы сейчас и занимаетесь.

Если это полезная нагрузка: {"Apple": True} Тогда, когда вы установите instance.fruit в validated_data["fruit"], ваше JSONField будет иметь замененное значение вместо обновленного. Для обновления сделайте следующее в serializers.py. instance.fruit = {**instance.fruit, **validated_data.get('fruit', instance.fruit)} Вот немного больше об операторе ** https://geekflare.com/python-unpacking-operators/

Вернуться на верх