用于通用视图的Django REST API自定义方法

时间:2016-10-18 04:31:08

标签: angularjs json django ionic-framework django-rest-framework

我是实习生,正在开发一个项目,我开发的DRF API需要与我的同事用Ionic框架编写的移动应用程序进行交互。 我们正在创造新用户。我的查看方法如下:

class NewUser(generics.CreateAPIView):
    model = User
    permission_classes = [permissions.AllowAny]
    serializer_class = NewUserSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        token, created = Token.objects.get_or_create(user=serializer.instance)
        return Response({'token': token.key}, status=status.HTTP_201_CREATED, headers=headers)

当有人想要通过POST请求创建新用户时如果尚未使用用户名,那么API将返回201状态代码和JSON中的令牌,如果已经使用了用户名,则返回400状态和JSON中的错误消息。我的同事要求我在尝试创建名称已存在的用户名时将状态消息更改为200。他说他不能消耗ERROR反应。 他的代码看起来像:

$http.post(url,{
username:$scope.tel,
password:$scope.passwd
}).success(function(data){
alert(data);
$ionicLoading.hide();
console.log(data);
})

问题: 1)我应该调整我的API以发送200状态而不是更多逻辑400用于'用户已注册'错误吗? 我试图改变我的代码,但我找不到在DRF的CreateAPIView / ModelSerializer中覆盖的方法。我最终将我的视图类重写为方法:

@api_view(['POST'])
def newUser(request):
    """
    Saves a new user on the database
    """
    if request.method == 'POST':

        serializer = NewUserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            token, created = Token.objects.get_or_create(user=serializer.instance)
            return Response({'token': token.key}, status=status.HTTP_201_CREATED, headers=serializer.data)
        else:
            return Response(serializer.errors, status=status.HTTP_200_OK)

问题: 2)如果我想改变API的行为并做出响应,我应该覆盖哪种方法 3)我是Django的新手,仍然不知道我们应该在哪里使用通用视图VS. @ ....方法

2 个答案:

答案 0 :(得分:0)

在这种情况下,200比400主要是偏好。 400表示“错误请求”。对于格式不正确的请求,这通常更为正确,而不是不符合某些条件的请求。

200恰当地传达了正确的信息:

您的请求有效,但我没有创建新记录。

关于如何进行覆盖。最短路径是覆盖CreateAPIView.create并更改使用的响应代码。您还应该通过调用CreateAPIView来避免重复super的默认行为。

class CreateUserView(generics.CreateAPIView):
    model = User
    permission_classes = [permissions.AllowAny]
    serializer_class = NewUserSerializer

    def create(self, request, *args, **kwargs):
        response = super(CreateUserView, self).create(request, *args, **kwargs)
        token, created = Token.objects.get_or_create(user=serializer.instance)
        response.status = status.HTTP_200_OK
        response.data = {'token': token.key}
        return response

就我个人而言,我还会设计我的NewUserSerializer以获得一个令牌字段并处理令牌,这样我就不必在View中完成这项工作。它不属于View

答案 1 :(得分:0)

保存和删除挂钩:

mixin类提供了以下方法,这些方法可轻松覆盖对象的保存或删除行为。

  

perform_create(self,serializer)-由CreateModelMixin调用,当   保存一个新的对象实例。 perform_update(self,serializer)-   保存现有对象实例时,由UpdateModelMixin调用。   perform_destroy(self,instance)-由DestroyModelMixin调用,当   删除对象实例。

这些钩子对于设置隐式存在于请求中但不属于请求数据的属性特别有用。例如,您可以基于请求用户或基于URL关键字参数在对象上设置属性。

https://www.django-rest-framework.org/api-guide/generic-views/#methods

class CourseOrder(generics.CreateAPIView):
    serializer_class = serializers.OrderCoursesSerializer
    permission_classes = [permissions.AllowAny]

    # hook before creating
    def perform_create(self, serializer):
        # print(serializer['name'].value)

        # save post data
        serializer.save()

        try:
            subject, from_email, to = 'New order', 'zelenchyks@gmail.com', 'zelenchyks@gmail.com'
            text_content = 'New order'
            html_content = '''
               <p>client name: %s </p>
               <p>client phone: %s </p>    
                ''' 
                % (serializer['name'].value, serializer['mobile'].value)

            msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
            msg.attach_alternative(html_content, "text/html")
            msg.send()
        except Warning:
            print('Huston we have a problems with smtp')