2015-11-02 14 views
9

Tôi có điểm cuối API cho phép người dùng đăng ký tài khoản. Tôi muốn trả lại HTTP 409 thay vì 400 cho tên người dùng trùng lặp.Khung làm việc Django REST cách chỉ định mã lỗi khi tăng lỗi xác thực trong bộ nối tiếp

Đây là serializer tôi:

from django.contrib.auth.models import User 
from rest_framework.serializers import ModelSerializer 

class UserSerializer(ModelSerializer): 
    username = CharField() 

    def validate_username(self, value): 
     if User.objects.filter(username=value).exists(): 
      raise NameDuplicationError() 
     return value 


class NameDuplicationError(APIException): 
    status_code = status.HTTP_409_CONFLICT 
    default_detail = u'Duplicate Username' 

Khi lỗi được kích hoạt, phản ứng là: {"detail":"Duplicate Username"}. Tôi nhận ra rằng nếu tôi phân lớp APIException, khóa detail được sử dụng thay vì username.

Tôi muốn có phản ứng này để thay thế {"username":"Duplicate Username"}

hoặc tôi muốn chỉ định một mã trạng thái khi nuôi một ValidationError:

def validate_username(self, value): 
    if User.objects.filter(username=value).exists(): 
     raise serializers.ValidationError('Duplicate Username', 
              status_code=status.HTTP_409_CONFLICT) 
    return value 

Nhưng điều này không làm việc như ValidationError chỉ trả về 400.

Có cách nào khác để thực hiện việc này không?

Trả lời

13

Bạn có thể tăng trường hợp ngoại lệ khác nhau như:

from rest_framework.exceptions import APIException 
from django.utils.encoding import force_text 
from rest_framework import status 


class CustomValidation(APIException): 
    status_code = status.HTTP_500_INTERNAL_SERVER_ERROR 
    default_detail = 'A server error occurred.' 

    def __init__(self, detail, field, status_code): 
     if status_code is not None:self.status_code = status_code 
     if detail is not None: 
      self.detail = {field: force_text(detail)} 
     else: self.detail = {'detail': force_text(self.default_detail)} 

bạn có thể sử dụng trong serializer của bạn như:

raise CustomValidation('Duplicate Username','username', status_code=status.HTTP_409_CONFLICT) 

hoặc

raise CustomValidation('Access denied','username', status_code=status.HTTP_403_FORBIDDEN) 
3

Sử dụng django-nghỉ ngơi-framework tùy chỉnh ngoại lệ handler http://www.django-rest-framework.org/api-guide/exceptions/

def custom_exception_handler(exc, context=None): 
    response = exception_handler(exc, context) 
    if response is not None: 
     if response.data['detail'] == 'Duplicate Username': 
      response.data['username'] = response.data.pop('detail') 
     response.status_code = status.HTTP_409_CONFLICT 
    return response 
+0

Tuyệt vời, tính năng này hoạt động. Hàm này sẽ trở nên rất phức tạp nếu tôi muốn tùy chỉnh ngoại lệ cho các khung nhìn khác nhau. Khi số lượt xem tăng, chức năng này cũng sẽ tăng lên. Tôi tự hỏi nếu có một giải pháp có thể mở rộng. – Cheng

+0

bạn muốn ghi đè 'chi tiết'? –

+0

Ý tôi là nếu có 3 ngoại lệ mà tôi muốn ghi đè, thì tôi sẽ có cấu trúc if..elif..elif trong 'custom_exception_handler'. Tôi muốn tùy chỉnh nhiều ngoại lệ, tôi càng phải viết nhiều hơn bằng phương pháp này. Ngoài ra, tôi cần phải nhớ chi nhánh nào chịu trách nhiệm về hoạt động HTTP của chế độ xem nào. Điều này có thể là một vấn đề thực sự xuống dòng. – Cheng

Các vấn đề liên quan