【问题标题】:DRF updating data using AJAX callDRF 使用 AJAX 调用更新数据
【发布时间】:2021-10-29 14:49:12
【问题描述】:

当我尝试通过前端向序列化程序发送数据时,我收到 HTTP 400 错误。如果我直接通过 DRF 可浏览 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 = ShipmentSerializer() 需要一个货件对象,而不是pk。试试改成shipment = serializers.PrimaryKeyRelatedField(queryset=Shipment.objects.all())看看能不能用
  • 您将请求内容类型设置为 application/json 但不发送 JSON
  • JSON.stringify 你的数据在发送 ajax 调用之前它会起作用
  • 这有点棘手。一种方法是创建一个用于创建的序列化程序,另一种用于显示。或者更改显示键的名称,例如显示时shipment_details,创建时shipment
  • 如果你想试试,我已经添加了答案

标签: django ajax django-rest-framework django-serializer


【解决方案1】:

解决此问题的一种方法是为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指定货件的id:

{
    "shipment_id": 10,
}

当您取货或列出时,货件详情将在shipment

{
    "serial": "",
    "shipment": {
        ... # shipment details
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-20
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    相关资源
    最近更新 更多