2017-08-16 72 views
1

這是我的模型:當HTTP POST請求的有效載荷爲空不完整的驗證消息

class Profile(models.Model): 
    user = models.OneToOneField(User) 
    phone = models.CharField(max_length=20, blank=True, null=True) 
    designation = models.CharField(max_length=50, blank=True, null=True) 
    roles = models.ManyToManyField(Role, related_name="profiles") 

,這是串行:

class UserSerializer(serializers.ModelSerializer): 
    email = serializers.EmailField(
     required=True, validators=[UniqueValidator(queryset=User.objects.all())]) 
    full_name = serializers.CharField(max_length=60, write_only=True) 
    phone = serializers.CharField(
     max_length=20, allow_blank=True, required=False, write_only=True) 
    designation = serializers.CharField(
     max_length=50, allow_blank=True, required=False, write_only=True) 
    roles = serializers.MultipleChoiceField(
     choices=models.Role.objects.values_list('id', flat=True), write_only=True) 

    class Meta: 
     model = User 
     fields = ('id', 'email', 'full_name', 'phone', 'designation', 'roles') 

問題

所有請求都與發送Content-Type: application/json

  1. 當我POST具有空淨荷的請求,DRF提出了一個400(不完全必需的字段)

    { 
        "full_name": [ 
        "required" 
        ], 
        "email": [ 
        "required" 
        ], 
    } 
    
  2. 當POST請求體是{},DRF提高400,與所有強制字段

    { 
        "full_name": [ 
        "required" 
        ], 
        "email": [ 
        "required" 
        ], 
        "roles": [ 
        "required" 
        ] 
    } 
    

問題

如何確保申請機構是空白的,DRF會提出ParseError

已經嘗試過

  1. 添加allow_blankrequired到角色中UserSerializer沒有任何效果。
  2. 使用APITestCase進行測試時沒有不一致性。我可以通過ARC重現錯誤。

解決方法

增加了一個自定義異常處理程序,檢查此:

request = context['request'] 
if request.content_type == 'application/json' and type(request.data) != dict: 
    return response.Response(
     {'detail': 'Invalid body'}, status=status.HTTP_400_BAD_REQUEST) 

當請求主體爲空,request.data是django.http.QueryDict。這是我正在檢查的。但是,我寧願在其起源處提出這個錯誤,而不是檢查它產生的副作用。

回答

1

對於正常的DRF功能,這似乎不可行。如果響應正文爲空,則request._parse()方法不會調用任何解析器,它只是返回默認的{}

這意味着您不能換出解析器並在某些端點上獲得所需的行爲。

# request.py @ 301 
if stream is None or media_type is None: 
    if media_type and not is_form_media_type(media_type): 
     empty_data = QueryDict('', encoding=self._request._encoding) 
    else: 
     empty_data = {} 
    empty_files = MultiValueDict() 
    return (empty_data, empty_files) 

parser = self.negotiator.select_parser(self, self.parser 

買者

你想要的行爲是有點不尋常;我認爲DRF現在正在正確地處理事情,但我可以看到爲什麼你會想要不同的行爲。也許這是DRF gihub中的一項功能請求? 「解析時添加allow_empty_body標誌(默認值爲True)。

注意:空請求主體是合法在發佈請求。例如,您可以使用它們觸發某個對象的操作,如post /api/accounts/592/disable/

如果您想要通過此操作,有幾種選擇,但它們都很笨拙,可能以某種方式破壞。

#1 Django的中間件

你可以寫一箇中間件類Django的檢查傳入的請求post和空體,並手動返回錯誤。

#2猴補丁的請求類

的,你可能會覆蓋在應用程序啓動時間與你的的DRF請求類的_parse()方法。

其他

可能可以做一些瘋狂的東西在你的序列化,或手動在一個空的請求post(self, request, **kwargs)方法來檢查,但他們都有點哈克。

+0

我忘了回覆,我的壞。我需要確保如果請求有效負載爲空,則'1')Django產生一個ValidationError(這可能不是正確的操作)或'2)Django返回正確的(和完整的)驗證錯誤。 您已經指出空的請求不是*非法*。所以,你覺得我怎麼可以修復'2)'? – Ajoy

+1

開始調試該MultipleChoice字段正在進行的操作。將它設置爲'required = True'?等我不知道爲什麼它可能不會總是返回完整的驗證錯誤。如果你可以用一個簡單的'Serializer'(不是ModelSerializer)和一個視圖來複制問題,那最好。那麼如果你無法弄清楚,也許別人可以。是的,留在試圖獲得完整和正確的錯誤。 –

+0

你有沒有設法重現「不完整的必填字段」問題?我記得看過幾次,或者想過我做過,但現在我明確地尋找它,我也無法重現它。 –

相關問題