2016-07-23 75 views
3

我将仅使用Django作为后端。前端将完成使用React和没有Django模板。我正在使用django-rest-framework为我的网站创建一个休息API。如何仅使用django后端并使用django-rest-framework发布

我为用户做了一个序列化器。

class CustomUserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = CustomUser 
     fields = (
      'id', 'email', 'password', 'username', 'first_name', 'last_name', 'date_of_birth', 'gender', 'mobile_number' 
     ) 
     extra_kwargs = { 
      'password': {'write_only': True}, 
      'id': {'read_only': True} 
     } 

    def create(self, validated_data): 
     user = CustomUser.objects.create(
      email=validated_data['email'], 
      username=validated_data['email'], 
      first_name=validated_data['first_name'], 
      last_name=validated_data['last_name'], 
      date_of_birth=validated_data['date_of_birth'], 
      gender=validated_data['gender'], 
      mobile_number=validated_data['mobile_number'] 
     ) 
     user.set_password(validated_data['password']) 
     user.save() 
     return user 

class CustomUserViewSet(viewsets.ModelViewSet): 
    queryset = CustomUser.objects.all() 
    serializer_class = CustomUserSerializer 

在浏览器中,当我去/ custom/users /时,我可以查看用户。我也可以创建新用户,在成功注册后返回用户。如果我使用httpie/curl,它也可以。

(djangoweb) [email protected]:~$ http --json POST http://55.55.55.5/custom/users/ email="[email protected]" password="terminal2123" username="t223erm" first_name="te2er" last_name="mi2nal" date_of_birth=1992-12-12 gender=2 mobile_number=66222666666336 

它创建并返回新的用户对象。

所以我做了一个表格要注册的我不是从Django的服务器服务用户:

<form action="http://55.55.55.5/custom/users/" method="post" id="register-form"> 
    <input type="text" placeholder="email" name="email"/> 
    ... 
    ... 
    <button id="post">Register</button> 
</form> 

和Ajax发布形式。

// using the javscript Cookies library 
var csrftoken = Cookies.get('csrftoken'); 

function csrfSafeMethod(method) { 
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
} 
$.ajaxSetup({ 
    beforeSend: function(xhr, settings) { 
     if (!csrfSafeMethod(settings.type) && !this.crossDomain) { 
      xhr.setRequestHeader("X-CSRFToken", csrftoken); 
     } 
    } 
}); 

$('#post').click(function(event) { 
    event.preventDefault(); 
    var $form = $('#register-form'); 
    var data = $form.serialize();   
    $.ajax({ 
     type: "POST", 
     url: "http://55.55.55.5/custom/users/", 
     data: JSON.stringify(data), 
     sucess: function() { console.log("Success!"); }, 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     crossDomain:false, 
     beforeSend: function(xhr, settings) { 
      xhr.setRequestHeader("X-CSRFToken", csrftoken); 
     } 
    }); 
}); 

现在后,如果我按一下按钮,问题开始:

  • 即使我给event.preventDefault()该页面会自动加载到Django的服务器的URL(即http://55.55.55.5/custom/users/)。
  • 我收到一个错误:“detail”:“CSRF失败:CSRF令牌丢失或不正确。”

如何使用django-rest-framework处理发送到django服务器的帖子?我没有找到任何有关此问题的帮助材料。你能指导我如何?谢谢。

+0

您能澄清谁在为前端页面提供服务吗?是由服务器直接呈现的静态HTML/JS,还是Django呈现它?假设它是一个静态文件,那么即使使用CSRF,我也不确定它是否有意义,因为您应该使用令牌或类似的安全性。 – dkarchmer

+0

@dkarchmer是的,它是由nodejs呈现的静态HTML/JS。我如何使用令牌如果我不是用户呢?我认为如果用户进行身份验证,就会得到令牌。你能指导我吗?谢谢。 – Robin

回答

3

您可以使用csrf_exempt进行注册和登录功能。作为一个例子,在这里如何创建注册和登录API。了解我的登录API如何返回令牌。见http://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication

我试图编辑我的代码来替换你的模型名称,但我没有测试它,所以你可能需要修复我有任何错别字(或让我知道,所以我可以修复它们)。

class AccountViewSet(viewsets.ModelViewSet): 
    queryset = CustomUser.objects.all() 
    serializer_class = CustomUserSerializer 

    def get_permissions(self): 

     if self.request.method in permissions.SAFE_METHODS: 
      return (permissions.IsAuthenticated(),) 

     if self.request.method == 'POST': 
      return (permissions.AllowAny(),) 

     return (permissions.IsAuthenticated(), IsAccountOwner(),) 

    @csrf_exempt 
    def create(self, request): 
     ''' 
     When you create an object using the serializer\'s .save() method, the 
     object\'s attributes are set literally. This means that a user registering with 
     the password \'password\' will have their password stored as \'password\'. This is bad 
     for a couple of reasons: 1) Storing passwords in plain text is a massive security 
     issue. 2) Django hashes and salts passwords before comparing them, so the user 
     wouldn\'t be able to log in using \'password\' as their password. 

     We solve this problem by overriding the .create() method for this viewset and 
     using Account.objects.create_user() to create the Account object. 
     ''' 

     serializer = self.serializer_class(data=request.data) 

     if serializer.is_valid(): 
      password = serializer.validated_data['password'] 
      confirm_password = serializer.validated_data['confirm_password'] 

      if password and confirm_password and password == confirm_password: 

       user = CustomUser.objects.create_user(**serializer.validated_data) 

       user.set_password(serializer.validated_data['password']) 
       user.save() 

       return Response(serializer.validated_data, status=status.HTTP_201_CREATED) 

     return Response({'status': 'Bad request', 
         'message': 'Account could not be created with received data.' 
         }, status=status.HTTP_400_BAD_REQUEST) 

class APILoginViewSet(APIView): 

    @csrf_exempt 
    def post(self, request, format=None): 
     data = JSONParser().parse(request) 
     serializer = LoginCustomSerializer(data=data) 

     if serializer.is_valid(): 
      email = serializer.data.get('email') 
      password = serializer.data.get('password') 

      if not request.user.is_anonymous(): 
       return Response('Already Logged-in', status=status.HTTP_403_FORBIDDEN) 

      user = authenticate(email=email, password=password) 

      if user is not None: 
       if user.is_active: 
        login(request, account) 

        serialized = UserSerializer(user) 
        data = serialized.data 

        # Add the token to the return serialization 
        try: 
         token = Token.objects.get(user=user) 
        except: 
         token = Token.objects.create(user=user) 

        data['token'] = token.key 

        return Response(data) 
       else: 
        return Response('This account is not Active.', status=status.HTTP_401_UNAUTHORIZED) 
      else: 
       return Response('Username/password combination invalid.', status=status.HTTP_401_UNAUTHORIZED) 

     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

    def get(self, request, format=None): 
     data_dic = {"Error":"GET not supported for this command"} 
     return Response(data_dic, status=status.HTTP_400_BAD_REQUEST) 

您可以在https://github.com/dkarchmer/django-aws-template看到一个完整的工作示例(声明,这是我的代码)。

希望这可以帮助您

相关问题