Как обновить значение в поле 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/