how to use ajax function to send form without page getting refreshed, what am I missing?Do I have to use rest-framework for this?

后端 未结 11 2149
花落未央
花落未央 2021-01-05 03:37

I\'m trying to send my comment form using ajax, right now when user inserts a comment then whole page gets refreshed. I want this to be inserted nicely without page getting

相关标签:
11条回答
  • 2021-01-05 04:21

    In your form tag below

    <form method="POST" action='{% url "comment_create" %}' id='commentForAjax'>{% csrf_token %}
    

    You don't need to define action or method. You handle them via ajax. So delete them and you form won't try to execute that action.And hopefully it will solve your refresh page issue.Also change your on submit line '.commentForAjax' into '#commentForAjax' since it is not a class but id.

    0 讨论(0)
  • 2021-01-05 04:22

    If the form is submitting it is not your backend code but your javascript code, you need to prevent the form from submitting, you can try changing this:

     <script>
         $(document).on('submit','.commentForAjax', function(e){
          e.preventDefault();
    

    To this:

    <script>
      $(document).ready(function(){
        $("#comentForAjax").submit(function(e){
          e.preventDefault();
    
          // Do whatever you need to do, like serializing the form and post with $.ajax
        });
      });
    

    So make sure you are binding the submit event right after the document loads so the browser knows that the form should not be submitted, and then you just make your ajax call and do whatever you need with the returned serialized data from the server.

    Again, if the form is posting, it doesn't have anything to do with the backend code.

    Note: For jquery selectors, if you need to select something by id you use the #element hash sign and if you want to target class selectors then you use the dot notation .elements. Also note that you can in theory select just one element by ID (given that you don't duplicate the ID for other elements) but classes are usually used to span several elements that share the same attributes.

    0 讨论(0)
  • 2021-01-05 04:23

    The main thing you need to do for preventing page reloading on form submit is calling event.preventDefault() in your form submit event handler. @Vibhu provided a very good code example in the answer above. That's exactly what you need to do on client side. (I provide his code with a single difference, request is sent to 'comment/create-ajax', not to 'comment/create'

    $(document).ready(function() {
    $("#commentForAjax").submit(function( event ) {
        $.ajax({
            type:'POST',
            url:'comment/create-ajax',
            data:{
                post_id:$('#post_id').val(),
                origin_path:$('#origin_path').val(),
                parent_id:$('#parent_id').val(),
                csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
            },
            success: function(response){
    
            }
        });
        event.preventDefault()
    });
    

    });

    On server side, you may provide one more controller (view in Django terms) which handles POST /comments/create-ajax, it should look somehow like this:

    def handle_comment_creation_via_ajax(request):
        comment_dict = json.loads(request.body)
        # or json.loads(request.body.decode("utf-8")) if you use python 3
        comment = CommentModel(**comment_dict) # This will work if comment has no nested models, otherwise, implement static method in your model class which takes dict and returns model instance.
        try:
            comment.save()
        except Exception as e:
            return JsonResponse({'success':false, 'message': str(e)}, status_code=400)
        return JsonResponse(model_to_dict(instance, fields=[], exclude=[])
    

    JsonResponse and model_to_dict

    Good luck!

    P.S. Note that incoming model must be validated before save

    0 讨论(0)
  • 2021-01-05 04:26

    $(document).on('submit','.commentForAjax', function(e){ e.preventDefault();

    // Put

    e.stopPropagation();

    0 讨论(0)
  • 2021-01-05 04:30

    For the sake of example, I would like to show how to achieve this using Django REST Framework and how much code you DON'T need to change.

    TL;DR

    Installing DRF doesn't break anything. Just add 8 lines of code (without imports), change 2 existing lines and get rid of your entire comment_create_view.

    For those who are interested in more details, please read further.

    1. Install django-rest-framework using this guide.

    2. Create a serializers.py file with the following contents

    class CommentSerializer(serializers.ModelSerializer):
        class Meta:
            model = Comment
            fields = '__all__'  # or specify the list of fields you want to be present
    

    Here you define the class that will serialize (transform a Comment model instance to a json object) and deserialize (inverse action of transforming a json object into a Comment instance) your comments.

    3. Add the following view to your views.py

    from rest_framework.generics import CreateAPIView
    class CommentCreateView(CreateAPIView):
        queryset = Comments.objects.all()
        serializer_class = CommentSerializer
    

    Note: These 4 lines of code actually substitute your whole comment_create_view.

    Here you define a generic view designed specifically for creation of objects. CreateAPIView will handle only POST requests and will use the CommentSerializer class to convert objects. A serializer class to Django REST framework is what a form class is to Django - it handles the validation of data and returns a response in form of json, or corresponding error messages (also in json) in case your data is not correct.

    4. Add the following to your main urls.py file

    url_patterns = [
        ...  # your urls here
        url(r'^api/v1/comments/$', CommentCreateView.as_view(), name='comments-list')
    ]
    

    Here you register your API view as a route to which you can send requests.

    5. Edit your ajax request

    $.ajax({
        type:'POST',
        url:'api/v1/comments/',  // switch to the API view url
        contentType: 'application/json',  // tell ajax to send it as `json` content
        data:{
          post_id:$('#post_id').val(),
          origin_path:$('#origin_path').val(),
          parent_id:$('#parent_id').val(),
          csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
        },
        success:function(json){
    

    You POST to the newly created API endpoint data in form of json and your serializer takes it and creates a Comment model instance from it that is saved to the database. In case you need some specific behavior while creating a Comment (or any other model) instance, you can override the .create() method of your CommentSerializer. For more details check the Django REST framework tutorial.

    6. Do whatever you need with the newly created comment

    This part applies to non Django REST framework scenarios as well. Once you've successfully created the comment, in your success function you will receive it in json form and depending on what you want to do with it, you need to define the desired behavior in this success function.

    Basically that's it. Please take into account that the example described here is a minimal required code to make it work for you. I've used the out-of-the-box Django REST framework features, but of course it has many more possibilities to make things work. Maybe you'll need to override some default methods, but in the end, because DRF is designed to deal with ajax calls, your code will be shorter and cleaner.

    Good luck!

    0 讨论(0)
提交回复
热议问题