Обновление данных DRF с помощью вызова AJAX
Когда я пытаюсь отправить данные через фронтенд в сериализатор, я получаю ошибку HTTP 400. Если я делаю это напрямую через DRF browsable API, то все работает:
модель:
class Shipment(models.Model):
name = models.CharField("name", max_length = 128)
date = models.DateField()
class Product(models.Model):
serial = models.CharField("serial", max_length = 31, unique = True)
shipment = models.ForeignKey(Shipment, on_delete = models.CASCADE, blank = True, null = True)
сериализатор:
class ShipmentSerializer(serializers.ModelSerializer):
class Meta:
model = Shipment
fields = ["id", "name",]
class ProductSerializer(serializers.ModelSerializer):
shipment = ShipmentSerializer()
def update(self, instance, request):
product = Product.objects.get(serial = instance)
product.shipment = Shipment.objects.get(id = request["shipment"]["id"])
product.save()
return instance
class Meta:
model = Product
fields = ["serial", "shipment",]
lookup_field = "serial"
read_only_fields = ["serial",]
Видовой набор:
class ProductViewSet(ModelViewSet):
serializer_class = ProductSerializer
lookup_field = "serial"
http_method_names = ["get", "patch", "put"]
def get_queryset(self):
return Product.objects.all()
Вызов AJAX:
$.ajax({url: `api/products/${serial}/`,
dataType: "json",
contentType: "application/json",
type: "PUT",
data: {"shipment": shipment[0]},
headers: {"X-CSRFTOKEN": csrf_token },
success: function () {window.location = "?msg=ok";},
error: function () {window.location = "?msg=error";}
});
Вывод браузера:
PUT
http://127.0.0.1:8000/api/products/d39f281f/
Status400
Bad Request
VersionHTTP/1.1
Transferred400 B (111 B size)
Referrer Policysame-origin
Полезная нагрузка запроса:
shipment=4
Ответ:
{"shipment":["This field is required."]}
или после некоторой игры:
JSON parse error - Expecting value: line 1 column 1 (char 0)
почему ответ field is required
при наличии полезной нагрузки.
Один из способов решения этой проблемы - определить два поля для shipment
, одно для записи, другое для чтения:
class ProductSerializer(serializers.ModelSerializer):
shipment_id = serializers.PrimaryKeyRelatedField(queryset=Shipment.objects.all(), write_only=True)
shipment = ShipmentSerializer(read_only=True)
class Meta:
model = Product
fields = ["serial", "shipment", "shipment_id"]
При обновлении вы можете указать идентификатор отправления, используя shipment_id
:
{
"shipment_id": 10,
}
При получении или размещении списка, информация об отправке будет представлена в разделе shipment
:
{
"serial": "",
"shipment": {
... # shipment details
}
}