从Django REST中的函数返回JsonResponse

时间:2019-11-19 10:21:18

标签: django

我有一个查询,其中所有字段都是必需的。我想确保他们吃饱了。事实证明,有很多重复的代码。因此,我决定创建一个函数,将字段中的值传递给该函数。但是请求继续,而不是发送响应代码400。

我的views.py

def pay(request):
    body = request.body.decode('utf-8')
    if not body:
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': 'empty query'
            },
        })
    body = json.loads(body)
    phone = body.get('phone')
    amount = body.get('amount')
    merch_name = body.get('merchant_name')
    #check_field(phone)
    if not phone:
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': 'phone field is empty'
            },
        })
    if not amount:
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': 'amount field is empty'
            },
        })
    if not merch_name:
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': 'merch_name field is empty'
            },
        })

我的功能:

def check_field(field):
    if not field:
        logger.info('its work')
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': '{} field is empty'.format(field)
            },
        })

我该如何解决?

3 个答案:

答案 0 :(得分:0)

我认为您的代码几乎正确,但是如果JsonResponse函数调用的返回值不是check_field,它应该返回一个None对象。 (如果函数调用未返回任何值,则实际上返回None

def pay(request):
    ...
    check_result = check_field(phone)
    if check_result is not None:
        return check_result
    ... (repeat ...)

无论如何,我建议您尝试使用Django REST Framework的Serializer。可以轻松解决这些参数检查问题。

答案 1 :(得分:0)

这是因为从被调用函数(check_field(phone))返回的值不会传播到调用方(pay函数)之外。 pay的责任是根据check_field的收益做出决定。

您有两种选择:

  • 将早期的long函数与辅助函数保持在一起,该辅助函数使您获得JsonResponse的传递字段,例如:

    def get_400_response(field_name):
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': f'{field_name} can not be empty'
            },
        })
    

    并通过pay函数,例如:

    if not phone:
        return get_400_response('phone')  # note the `return` here
    
  • 如果您想使用check_field,则可以保持原样,然后从pay检查返回值是否为JsonReponse,如果返回,则返回将其保存为有效值:

    phone = body.get('phone')
    if isinstance(phone, JsonResponse):
        return phone
    
  • 另一种选择是引发异常,例如ValidationError函数中的check_field,而不是进行isinstance检查,而是在try-except中进行处理,因此本质上是鸭式输入。


更好的方法: 最好汇总所有字段中的所有错误并将其作为单个响应发送,这样可以提高可用性。因此,您可以创建一个仅执行验证的功能(根据需要利用其他小功能),并发送验证后的数据或ValidationError来获取无效数据,您可以从pay处理它。

答案 2 :(得分:0)

请注意,您的check_field不能按原样工作,因为field是指值,而不是您传入的变量的名称。

使用异常可以避免代码重复:

from django.core.exceptions import ValidationError

def pay(request):
    try
        body = request.body.decode('utf-8')
        if not body:
            raise ValidationError('empty query')
        body = json.loads(body)
        for field_name in ['phone', 'amount', 'merchant_name']:
            check_field(body, field_name)
    except ValidationError as error:
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': error.message
            },
        })

 def check_field(data, field_name):
     if not data.get(field_name):
         raise ValidationError('{} field is empty'.format(field_name)

我赞同@youngminz的建议,以研究Django REST Framework序列化程序。另外,您也可以使用常规的Django表单。

如果amount是数字,而0是有效值,则必须使用data.get(field_name) is None进行支票。