简体   繁体   English

如何使用django只有一个后端并使用django-rest-framework发布

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

I will be using Django only as the backend. 我将仅使用Django作为后端。 The front end will be done using React and no django templates. 前端将使用React而不是django模板完成。 I am using django-rest-framework to create a rest api for my website. 我正在使用django-rest-framework为我的网站创建一个rest api。

I made a serializer for the user. 我为用户制作了一个序列化器。

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

In the browser, when I go to /custom/users/ I can view the users. 在浏览器中,当我转到/ custom / users /我可以查看用户。 I can also create new users which after successful registration returns back the user. 我还可以创建新用户,在成功注册后返回用户。 Also it works if I use httpie/curl. 如果我使用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

It creates and returns the new user object. 它创建并返回新的用户对象。

So I made a form to register a user which I am not serving from the django server: 所以我创建了一个表单来注册一个我没有从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>

And ajax to post the 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);
        }
    });
});

Now after if I click the button, the problem starts: 现在,如果我单击按钮,问题就开始了:

  • Even though I gave event.preventDefault() the page is automatically loaded to the url of the django server (ie, http://55.55.55.5/custom/users/ ). 即使我给了event.preventDefault() ,页面也会自动加载到django服务器的url(即http://55.55.55.5/custom/users/ )。
  • I get an error: "detail": "CSRF Failed: CSRF token missing or incorrect." 我收到一个错误:“detail”:“CSRF失败:CSRF令牌丢失或不正确。”

How can I handle the post to the django server using django-rest-framework? 如何使用django-rest-framework处理django服务器的帖子? I didn't find any helping material for this problem. 我找不到任何有关这个问题的帮助材料。 Could you please guide me how to? 你能指导我怎么样吗? Thank you. 谢谢。

You can use csrf_exempt for the registration and login functions. 您可以使用csrf_exempt进行注册和登录功能。 As an example, here how you can create the registration and login APIs. 例如,在这里您可以创建注册和登录API。 See how my login API returns the token. 查看我的登录API如何返回令牌。 See http://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication . 请参阅http://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication

I tried to edit my code to replace with your model names, but I did not test it, so you may need to fix any typos I have (or let me know so I can fix them). 我试图编辑我的代码以替换你的模型名称,但我没有测试它,所以你可能需要修复我有的任何错别字(或让我知道所以我可以解决它们)。

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)

You can see a full working example at https://github.com/dkarchmer/django-aws-template (disclaimer, that's my code). 您可以在https://github.com/dkarchmer/django-aws-template上看到一个完整的工作示例(免责声明,这是我的代码)。

Hope this helps you 希望这对你有所帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Ajax / jQuery / Javascript在Django-REST-Framework中访问和使用令牌认证并在前端显示API结果 - How to Access and use Token Authentication and show API result at the front end in Django-REST-Framework with Ajax/jQuery/Javascript 从django-rest-framework返回JSON以用于表可视化前端 - Returning JSON from django-rest-framework for use in table visualization front end Django-Autocomplete-Light Widget在Django-Rest-Framework中导致较长的加载时间 - Django-Autocomplete-Light Widget causing long loading times in Django-Rest-Framework 如何使DRF(Django-REST-Framework)令牌持久存在,以便在每次刷新页面后不会丢失它? - How to make the DRF ( Django-REST-Framework) Token persist so that it does not get lost after each page refresh? 如何从Django Rest Framework中的多个选择框中发布数据 - How to POST data from a multiple select box in Django Rest Framework 如何在Django Rest框架中添加评论框和发布表单 - How to add comment box and post form to django rest framework 如何使用带有Ajax的DJANGO REST框架发出POST请求 - How to make a POST request using DJANGO REST framework with ajax 具有外键字段的Django rest框架POST - Django rest framework POST with a foreign key field 使用HTML页面或模板中的Django-REST-Framework从Django中创建的API的前端获取/显示API数据 - Get/Display API data at front end from an API created in Django using Django-REST-Framework in an HTML page or Template 如何在django上使用$ .post? - How to use $.post with django?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM