【问题标题】:Django RestFramework POST nested requestDjango Rest Framework POST 嵌套请求
【发布时间】:2023-01-08 20:44:31
【问题描述】:

我现在在使用 Django Rest Framework 时遇到了一点问题。我正在尝试发布一个包含嵌套对象的对象。

这是我的models.py 文件。

class Supplier(models.Model):
    name = models.CharField(max_length=255, blank=True, null=True)

    def __str__(self):
        return self.name
class Transaction(models.Model):
    date = models.CharField(max_length=255, blank=True, null=True)
    income = models.IntegerField(blank=True,null=True)
    expense = models.IntegerField(blank=True,null=True)
    card = models.CharField(max_length=255, blank=True, null=True)
    currency = models.CharField(max_length=255, blank=True, null=True)
    supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
    category = models.CharField(max_length=255, blank=True, null=True)

    def __str__(self):
        return self.date + ' ' + str(self.expense) + ' ' + self.card + ' ' + str(self.supplier)

这是我的serializers.py 文件

class SupplierSerializer(serializers.ModelSerializer):
    class Meta:
        model = Supplier
        fields = ['id', 'name']


class TransactionSerializer(serializers.ModelSerializer):
    supplier = SupplierSerializer()
    class Meta:
        model = Transaction
        fields = ['id',
                  'date',
                  'income',
                  'expense',
                  'card',
                  'currency',
                  'supplier',
                  'category']
        read_only_fields = ['id']

    def create(self, validated_data):
        supplier_data = validated_data.pop('supplier')
        supplier = Supplier.objects.create(**supplier_data)
        transaction = Transaction.objects.create(supplier=supplier, **validated_data)

        return transaction

这是我的views.py 文件

@api_view(['POST', 'GET'])
def transaction(request):

    if request.method == 'POST':
        transaction_serializer = TransactionSerializer(data=request.data)
        if transaction_serializer.is_valid():
            transaction_serializer.save()
            return Response(transaction_serializer.data, status=status.HTTP_201_CREATED)

    if request.method == 'GET':
        transactions = Transaction.objects.all()
        serializer = TransactionSerializer(transactions, many = True)
        return JsonResponse(serializer.data, safe=False)

我正在尝试发出此 POST 请求:

{
    "date": "12/10/2022",
    "income": 41241,
    "expense": null,
    "card": "Credit card",
    "currency": "CLP",
    "supplier": [{
      "name": "Cabify"
    }],
    "category": "Transporte"
}

但在控制台中显示此错误:

[28/Nov/2022 19:50:56] "POST /transactions/ HTTP/1.1" 500 73587
Internal Server Error: /transactions/
Traceback (most recent call last):
  File "/Users/benjaminandaur/Desktop/projects/drinks-api/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/Users/benjaminandaur/Desktop/projects/drinks-api/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 191, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/benjaminandaur/Desktop/projects/drinks-api/venv/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/benjaminandaur/Desktop/projects/drinks-api/venv/lib/python3.9/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/benjaminandaur/Desktop/projects/drinks-api/venv/lib/python3.9/site-packages/rest_framework/views.py", line 513, in dispatch
    self.response = self.finalize_response(request, response, *args, **kwargs)
  File "/Users/benjaminandaur/Desktop/projects/drinks-api/venv/lib/python3.9/site-packages/rest_framework/views.py", line 424, in finalize_response
    assert isinstance(response, HttpResponseBase), (
AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'NoneType'>`
[28/Nov/2022 19:54:33] "POST /transactions/ HTTP/1.1" 500 73587

【问题讨论】:

    标签: django django-models django-rest-framework django-views django-serializer


    【解决方案1】:

    我认为存在序列化问题,因此您需要处理序列化程序无效的情况,以获取问题的根源:

    @api_view(['POST', 'GET'])
    def transaction(request):
    
        if request.method == 'POST':
            transaction_serializer = TransactionSerializer(data=request.data)
            if transaction_serializer.is_valid():
                transaction_serializer.save()
                return Response(transaction_serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(transaction_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
        if request.method == 'GET':
            transactions = Transaction.objects.all()
            serializer = TransactionSerializer(transactions, many = True)
            return JsonResponse(serializer.data, safe=False)
    

    我认为你的序列化程序的问题是你发送了一份供应商列表

    "supplier": [{
          "name": "Cabify"
        }]
    

    在你的序列化器中你只创建了一个,而在你的模型中它是一个 ForeignKey 所以你的序列化器是正确的引用你的模型所以我认为你需要改变你的发布请求:

    {
        "date": "12/10/2022",
        "income": 41241,
        "expense": null,
        "card": "Credit card",
        "currency": "CLP",
        "supplier": {
          "name": "Cabify"
        },
        "category": "Transporte"
    }
    

    或者如果您无法控制 POST 请求

    您可以更改您的序列化程序创建方法并像这样选择供应商列表的第一个元素:

    类 TransactionSerializer(序列化器.ModelSerializer): 供应商 = SupplierSerializer() 类元: 模型 = 事务 字段 = ['id', '日期', '收入', '费用', '卡片', '货币', '供应商', '类别'] read_only_fields = ['id']

    def create(self, validated_data):
        supplier_data = validated_data.pop('supplier')
        if supplier_data:
            supplier = Supplier.objects.create(**supplier_data[0])
        transaction = Transaction.objects.create(supplier=supplier, **validated_data)
    
        return transaction
    

    【讨论】:

      【解决方案2】:

      来自 DRF api_view 装饰器documentation,视图将是这样的:

      @api_view(['GET', 'POST'])
      def transaction(request):
          if request.method == 'POST':
              transaction_serializer = TransactionSerializer(data=request.data)
              if transaction_serializer.is_valid():
                  transaction_serializer.save()
              return Response({"status": status.HTTP_201_CREATED, "data": serializer.data})
          
          transactions = Transaction.objects.all()
          serializer = TransactionSerializer(transactions, many = True)
          return Response({"data": serializer.data})
      

      【讨论】:

      • 如果它无效,则无法获得序列化程序
      猜你喜欢
      • 1970-01-01
      • 2018-12-20
      • 2014-10-03
      • 2018-09-22
      • 1970-01-01
      • 2018-05-19
      • 2019-05-04
      • 1970-01-01
      • 2016-05-31
      相关资源
      最近更新 更多