【问题标题】:Django, updating DB column, rest_frameworkDjango,更新数据库列,rest_framework
【发布时间】:2020-02-27 07:03:49
【问题描述】:

在更新数据库中的列时有点卡住。我正在发送put 更新列的请求。但返回错误。

assert isinstance(response, HttpResponseBase), ( AssertionError: 预期为 ResponseHttpResponseHttpStreamingResponse 从视图返回,但收到<class 'NoneType'>

这里是前端。发送request

updateInvoceProject(id, company_name){
    return axios.put(API_HANDLER.database_api + "api/v1/update-project", {id, company_name})
},

serializer.py

class InvocesSerializer(serializers.ModelSerializer):
    class Meta:
        model = Invoces
        fields = ("__all__")

查看

@csrf_exempt 
@api_view(["PUT"])
def update(request):
    if request.method == "PUT":
        serializer = InvocesSerializer(data=request.data)
        if serializer.is_valid():
            invoce = Invoces.objects.get(id=serializer.data["id"])
            invoce.company_name = serializer.data["company_name"]
            invoce.save()

            return Response(serializer.data)

网址

urlpatterns = [
    #
    path("api/v1/update-project", invocesView.update, name="update-project"),
    #
]

但最后,我上面提到的错误弹出了。我在这里错过了什么吗?

【问题讨论】:

  • 当序列化器无效或未放置方法时,您不会返回任何内容。

标签: django django-rest-framework


【解决方案1】:

发生这种情况是因为当序列化数据无效时您没有返回任何内容。

你可以简单地把它变成这样,以确保它在所有情况下都会返回一些东西。

@csrf_exempt 
@api_view(["PUT"])
def update(request):
    # if request.method == "PUT":
    # You don't have to check for method, since you already defined it
    # in api_view(...) decorator.
    serializer = InvocesSerializer(data=request.data)
    # Raises a ValidatinException which will be sent as a 400 response.
    serializer.is_valid(raise_exception=True)
    invoce = Invoces.objects.get(id=serializer.data["id"])
    invoce.company_name = serializer.data["company_name"]
    invoce.save()
    return Response(serializer.data)

更好的解决方案

我建议你使用 DRF 的UpdateAPIView (Do it the DRF way :D),为了避免陷入这样的错误,也避免做所有的验证和序列化手。

如下:

1.保留您的InvocesSerializer,并创建另一个仅用于更新company_name

# Inside serializers.py
class InvocesCompanyNameUpdateSerializer(serializers.ModelSerializer):

    def to_representation(self, instance):
        return InvocesSerializer(instance).to_representation(instance)

    class Meta:
        model = Invoces
        fields = ('company_name',)

2 。为该序列化程序创建一个UpdateAPIView

# Inside views.py
class InvoiceUpdateCompanyNameAPIView(UpdateAPIView):
    http_method_names = ['put'] # This is only to allow PUT method on this view.
    serializer_class = InvocesCompanyNameUpdateSerializer
    queryset = Invoces.objects.all()

3 .现在将带有re_path 的视图附加到您的网址。

# Inside urls.py
urlpatterns = [
    #
    # you have to add "pk" url path variable, so DRF use it internally to identify
    # which object you want to update.
    re_path(r"api/v1/update-project/(?P<pk>[\d]+)/", 
        invocesView.InvoiceUpdateCompanyNameAPIView.as_view(), 
        name="update-project"),
    #
]

【讨论】:

  • 感谢您的回答。我明白你关于为更新创建新的序列化程序的观点。最后也看到了问题。它期望所有列名都可以序列化,但只会得到company_name。问题是 DRF 方式 的逻辑对我来说有点偏离,为什么我需要编写一个不同的类来只更新一列?如果我对每张桌子都这样做。然后会有一堆代码......并在re_path中使用正则表达式来获得id......在问题中的视图中执行它不是更简单吗?因为乍一看,它肯定看起来很复杂。
猜你喜欢
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2014-08-21
  • 2014-08-29
  • 2012-03-06
  • 1970-01-01
相关资源
最近更新 更多