django-rest-framework
django-rest-framework copied to clipboard
In browsable API unselecting the checkbox for a boolean field doesn't update the field, but using raw data does update the field
I noticed that when I unselect the boolean field that was already True to set it to False via browsable API – the field doesn't update.
Here's an example: https://capture.dropbox.com/k3xcrwjBS9aK4fVT
After unselecting "invoiced" and clicking PUT, the data stays the same (I edited the price value too): https://capture.dropbox.com/bT46reH9ushS8nge
But when I edit the RAW data text field: https://capture.dropbox.com/pDYjaAHHsvNqE79K
The value gets updated: https://capture.dropbox.com/mC9UwhQBLrt1yEOE
It works on all of my endpoints the same way. I wonder if this is a bug or if I am doing something wrong.
Just FYI, GitHub allows you to upload images 😅 It would be helpful if you share also some code to see what may be happening here.
Here is the model:
` class Currency(TimeStampedModel): company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="companies") name = models.CharField(choices=settings.CURRENCY_CHOICES, default='USD', max_length=3) owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "Currencies"
def __str__(self):
return self.name
``
here's the serializer:
`class CurrencySerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) company = serializers.PrimaryKeyRelatedField(read_only=True) name = serializers.ChoiceField(choices=settings.CURRENCY_CHOICES) owner = serializers.StringRelatedField()
class Meta:
model = Currency
fields = '__all__'
def create(self, validated_data):
return Currency.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.company = validated_data.get('company', instance.company)
instance.owner = validated_data.get('owner', instance.owner)
instance.save()
return instance`
here're the views:
`class CurrencyListCreateAPIView(generics.ListCreateAPIView): serializer_class = CurrencySerializer permission_classes = [ IsAuthenticated, IsOwner, ]
def perform_create(self, serializer):
user = self.request.user
kwarg_company = self.kwargs.get("company")
company = get_object_or_404(Company, pk=kwarg_company, owner=user)
if serializer.is_valid():
currency_name = serializer.validated_data['name']
if company:
if Currency.objects.select_related('owner', 'company').filter(company_id=kwarg_company).filter(
name=currency_name).exists():
raise ValidationError(
"You have already added this currency!")
else:
return serializer.save(owner=user, company=company)
else:
raise ValidationError("You don't own that Company")
def get_queryset(self):
user = self.request.user
kwarg_company = self.kwargs.get("company")
return Currency.objects.select_related('company', 'owner').filter(
owner=user).filter(
company_id=kwarg_company).order_by("-created_at")`
Sorry, I don't know how to post the code so it is correctly shown.
Hi, is that issue already solved? If not - can I work on it?
It is not solved for me 🙂
Hi, is that issue already solved? If not - can I work on it?
you can work on it.
ListCreateAPIView
this code is not right, ListCreateAPIView only support get and post, not support put
Please, use the ModelViewSet
and ModelSerializers
https://www.django-rest-framework.org/api-guide/serializers/#modelserializer
https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset
class CurrencySerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
company = serializers.PrimaryKeyRelatedField(read_only=True)
name = serializers.ChoiceField(choices=settings.CURRENCY_CHOICES)
owner = serializers.StringRelatedField()
class Meta:
model = Currency
fields = ["id", "company", "name", "owner"]
You can spli the serializer and use different serializer in ModelViewSet with def_get_serializer_class base on self.action
Like:
# views.py
from rest_framework import viewsets
class MyModelViewSet(viewsets.ModelViewSet):
# other
def get_serializer_class(self):
if self.action == "create":
# return create serializer class
elif self.action in ["update", "partial_update"]:
# return the serualizer class made for the PATCH/PUT
# made last one for the list/retieve action
#serializers.py
class CurrencyUpdateSerializer(serializers.ModelSerializer):
name = serializers.ChoiceField(choices=settings.CURRENCY_CHOICES)
owner = serializers.StringRelatedField()
class Meta:
model = Currency
fields = ["name", "owner"]
class CurrencyRetrieveListSerializer(serializers.ModelSerializer):
class Meta:
fields = "__all__"
You have more control for action of drf and the HTTP method https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions
Hi, is that issue already solved? If not - can I work on it?
you can work on it.
I'm facing this same issue as well. Do you guys know when it could be fixed?