如何仅使用 django 后端和 post 与 django-rest-framework

How to use django only a backend and post with django-rest-framework

我将只使用 Django 作为后端。前端将使用 React 完成,不使用 django 模板。我正在使用 django-rest-framework 为我的网站创建休息 api。

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

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/ 时,我可以查看用户。我还可以创建新用户,在成功注册 returns 后返回用户。如果我使用 httpie/curl.

它也有效
(djangoweb) vagrant@precise32:~$ http --json POST http://55.55.55.5/custom/users/ email="ter23minal2@gmail.com" password="terminal2123" username="t223erm" first_name="te2er" last_name="mi2nal" date_of_birth=1992-12-12 gender=2 mobile_number=66222666666336

它创建并 returns 新的用户对象。

所以我做了一个表格来注册一个我不是从 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到post表格。

// 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);
        }
    });
});

现在,如果我点击按钮,问题就开始了:

如何使用 django-rest-framework 将 post 处理到 django 服务器?对于这个问题,我没有找到任何帮助 material。你能指导我怎么做吗?谢谢。

您可以使用csrf_exempt进行注册和登录功能。例如,这里是如何创建注册和登录 APIs。看看我如何登录API returns token。参见 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 查看完整的工作示例(免责声明,那是我的代码)。

希望对您有所帮助