Poula Adel
Poula Adel

Reputation: 639

Django Ajax: response renders in another page not same page

I'm having app that using ajax to submit model form.

ISSUE: the submit works fine and edit the database. but the response renders in manage_user("users/manage" in another wod), not the same page I'm working on "users/"

in urls.py:

path('users/', views.users, name = 'users'),
path('users/manage', views.manage_users, name = 'manage_users'),

in views.py:

@login_required(login_url="/login/")
def users(request):
    #Defining Needed variables
    context = {}
    crud = CRUDHandler()
    queryset = Q() #if filters applied to crud or formset
    #Getting data for view
    crud.fields=['username','first_name','last_name','email','id']
    dataset=crud.r_user()
    #Adding data to context
    context['dataset']=dataset
    context['dataset_title']= 'User'
    context['handle_url']='manage_users'
    return TemplateResponse(request,'table-view.html',context)

@login_required(login_url="/login/")
def manage_users(request):
    done = []
    fail = []
    form = None
    context = {}
    template_path = ""

    if 'edit'in request.POST:
        instance_id = request.POST.get('instance_id')
        user = get_object_or_404(User,pk=instance_id)
        form = UserInfoForm(request.POST or None,instance=user)
        if form.is_valid():
            exsisting_user = form.save()
            if isinstance(exsisting_user,User):
                done.append("User "+exsisting_user.first_name+" updated successfully!")
            else:
                fail.append(exsisting_user) # returning errors
        else:
            fail.append("Somthing went wrong, check your input!")
        template_path = "components/forms/instance_edit_form.html"
    
    # reload users
    crud.fields=['username','first_name','last_name','email','id']
    dataset=crud.r_user()
    # construct the context
    context['done'] = done
    context['fail'] = fail
    context['dataset'] = dataset
    context['form'] = form
    context['handle_url'] = 'manage_users'
    # load form template
    html_form = loader.render_to_string(template_path, context, request)
    # load table template
    html_table = loader.render_to_string( "components/tables/model-table-view.html", context, request )
    return JsonResponse({'form':html_form,'table':html_table,'done':done,'fail':fail})

in handler.js:

$(document).ready(function(){
    /* load form */
    var loadForm = function () {
      var btn = $(this);
      $.ajax({
        url: btn.attr("data-url"),
        type: 'POST',
        data: btn.parents("form").serialize(),
        dataType: 'json',
        beforeSend: function () {
          $("#modal_form .modal-content").html("");
          $("#modal_form").modal("show");
        },
        success: function (data) {
          $("#modal_form .modal-content").html(data.form);
        },
        error : function(xhr,errmsg,err) {
          $("#modal_form .modal-content").html(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
        },
      });
      return false;
    };
    /* save form */
    var saveForm = function () {
      var form = $(this);
      $.ajax({
        url: form.attr("action"),
        data: form.serialize(),
        type: 'POST',
        dataType: 'json',
        success: function (data) {
          if (data.done) {
            $("#modal_form").modal("hide");
            $("#datatable_feature").parent().html(data.table);
          }
          else {
            // $("#modal_form").modal("show");
            $("#modal_form .modal-content").html(data.form);
          }
        },
        error : function(xhr,errmsg,err) {
          $("#modal_form .modal-content").html(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
        },
      });
      return false;
    };
  
  
    /* Binding */
    // View instance
    $(".js-view-inst-btn").on("click", loadForm);
  
    // Create instance
    $(".js-add-inst-btn").on("click", loadForm);
    $("#modal_form form").on("submit", ".js-instance-create-form", saveForm);
  
    // Update instance
    $(".js-edit-inst-btn").on("click", loadForm);
    $("#modal_form form").on("submit", ".js-instance-update-form", saveForm);
  
    // Delete instance
    $(".js-del-inst-btn").on("click", loadForm);
    $("#modal_form form").on("submit", ".js-instance-delete-form", saveForm);
});

the table view /components/tables/model-table-view.html:

{% if done %}
    <div class="card bg-success text-white shadow">
        <ul>
            {% for success_msg in done %}
                <li> {{success_msg}} </li>
            {% endfor %}
        </ul>
    </div>
{% endif %}
<table id="datatable_feature" class="table table-bordered table-striped">
    <thead>
        {% for row in dataset|slice:":1" %}
            <tr>
                {% for field in row %}
                    {% ifequal field 'id' %}
                        <td>Options</td>
                    {% else %}
                        <td>{{field}}</td>
                    {% endifequal %}
                {% endfor %}
            </tr>
        {% endfor %}
    </thead>
    <tbody>
        {% for row in dataset %}
            <tr>
                {% for key,value in row.items %}
                    {% ifequal key 'id' %}
                        <td>
                            <form method="POST" action="{% url handle_url %}">
                                {% csrf_token %}
                                <input type="hidden" name="instance_id" value="{{ row.id }}"></input>
                                <input type="hidden" name="get_edit" value="{{ row.id }}"></input>
                                <button type="button" class="btn btn-warning btn-sm js-edit-inst-btn" data-url="{% url handle_url %}">
                                    <i class="fas fa-edit"></i> Edit
                                </button>
                            </form>
                            <form method="POST" action="{% url handle_url %}">
                                {% csrf_token %}
                                <input type="hidden" name="instance_id" value="{{ row.id }}"></input>
                                <input type="hidden" name="get_view" value="{{ row.id }}"></input>
                                <button type="button" class="btn btn-primary btn-sm js-view-inst-btn" data-url="{% url handle_url %}">
                                    <i class="fas fa-eye"></i> View
                                </button>
                            </form>
                            <form method="POST" action="{% url handle_url %}">
                                {% csrf_token %}
                                <input type="hidden" name="instance_id" value="{{ row.id }}"></input>
                                <input type="hidden" name="get_delete" value="{{ row.id }}"></input>
                                <button type="button" class="btn btn-danger btn-sm js-del-inst-btn" data-url="{% url handle_url %}">
                                    <i class="fas fa-trash-alt"></i> Delete
                                </button>
                            </form>
                        </td>
                    {% else %}
                        <td>{{value}}</td>
                    {% endifequal %}
                {% endfor %}
            </tr>
        {% endfor %}
    </tbody>
    <tfoot>
        {% for row in dataset|slice:":1" %}
            <tr>
                {% for field in row %}
                    {% ifequal field 'id' %}
                        <td>Options</td>
                    {% else %}
                        <td>{{field}}</td>
                    {% endifequal %}
                {% endfor %}
            </tr>
        {% endfor %}
    </tfoot>
</table>

the form view /components/forms/instance_edit_form.html:

<form method="POST" action="{% url handle_url %}">
    {% csrf_token %}
    <div class="modal-header">
        <h4 class="modal-title">{{ dataset_title }} Edit Info</h4>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        {% if fail %}
            <div class="card bg-danger text-white shadow">
                <ul>
                    {% for fail_msg in fail %}
                        <li> {{fail_msg}} </li>
                    {% endfor %}
                </ul>
            </div>
        {% endif %}
        {%comment%}
            render form here
        {%endcomment%}
        <table>
            {{form.as_table}}
        </table>
    </div>
    <div class="modal-footer justify-content-between">
        <input type="hidden" name="instance_id" value="{{form.instance.id}}"/>
        <button type="submitt" name="edit" class="btn btn-primary">Save changes</button>
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    </div>
</form>

Table View table-view.html:

{% extends "layouts/base.html" %}

{% block title %} Edu Portal {% endblock %} 

<!-- Element injected in the BODY element -->
{% block body_class %} {{dataset_title}} {% endblock body_class %} 

<!-- Specific Page CSS goes HERE  -->
{% block stylesheets %}


  <!-- Google Font: Source Sans Pro -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
  <!-- Font Awesome -->
  <link rel="stylesheet" href="/static/assets/plugins/fontawesome-free/css/all.min.css">
  <!-- DataTables -->
  <link rel="stylesheet" href="/static/assets/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css">
  <link rel="stylesheet" href="/static/assets/plugins/datatables-responsive/css/responsive.bootstrap4.min.css">
  <!-- Theme style -->
  <link rel="stylesheet" href="/static/assets/css/adminlte.min.css">
  

{% endblock stylesheets %}

{% block content %}  

  <div class="content-wrapper">
    <!-- Content Header (Page header) -->
    <section class="content-header">
        <div class="card">
            <div class="card-header">
                <h3 class="card-title">{{dataset_title}}s Table Management</h3>
            </div>
            <!-- /.card-header -->
            <div class="card-body">
                {% if done %}
                    <div class="card bg-success text-white shadow">
                        <ul>
                            {% for success_msg in done %}
                                <li> {{success_msg}} </li>
                            {% endfor %}
                        </ul>
                    </div>
                {% endif %}
                <table id="datatable_feature" class="table table-bordered table-striped">
                    <thead>
                        {% for row in dataset|slice:":1" %}
                            <tr>
                                {% for field in row %}
                                    {% ifequal field 'id' %}
                                        <td>Options</td>
                                    {% else %}
                                        <td>{{field}}</td>
                                    {% endifequal %}
                                {% endfor %}
                            </tr>
                        {% endfor %}
                    </thead>
                    <tbody>
                        {% for row in dataset %}
                            <tr>
                                {% for key,value in row.items %}
                                    {% ifequal key 'id' %}
                                        <td>
                                            <form method="POST" action="{% url handle_url %}">
                                                {% csrf_token %}
                                                <input type="hidden" name="instance_id" value="{{ row.id }}"></input>
                                                <input type="hidden" name="get_edit" value="{{ row.id }}"></input>
                                                <button type="button" class="btn btn-warning btn-sm js-edit-inst-btn" data-url="{% url handle_url %}">
                                                    <i class="fas fa-edit"></i> Edit
                                                </button>
                                            </form>
                                            <form method="POST" action="{% url handle_url %}">
                                                {% csrf_token %}
                                                <input type="hidden" name="instance_id" value="{{ row.id }}"></input>
                                                <input type="hidden" name="get_view" value="{{ row.id }}"></input>
                                                <button type="button" class="btn btn-primary btn-sm js-view-inst-btn" data-url="{% url handle_url %}">
                                                    <i class="fas fa-eye"></i> View
                                                </button>
                                            </form>
                                            <form method="POST" action="{% url handle_url %}">
                                                {% csrf_token %}
                                                <input type="hidden" name="instance_id" value="{{ row.id }}"></input>
                                                <input type="hidden" name="get_delete" value="{{ row.id }}"></input>
                                                <button type="button" class="btn btn-danger btn-sm js-del-inst-btn" data-url="{% url handle_url %}">
                                                    <i class="fas fa-trash-alt"></i> Delete
                                                </button>
                                            </form>
                                        </td>
                                    {% else %}
                                        <td>{{value}}</td>
                                    {% endifequal %}
                                {% endfor %}
                            </tr>
                        {% endfor %}
                    </tbody>
                    <tfoot>
                        {% for row in dataset|slice:":1" %}
                            <tr>
                                {% for field in row %}
                                    {% ifequal field 'id' %}
                                        <td>Options</td>
                                    {% else %}
                                        <td>{{field}}</td>
                                    {% endifequal %}
                                {% endfor %}
                            </tr>
                        {% endfor %}
                    </tfoot>
                </table>
            </div>
            <!-- /.card-body -->
            <div class="card-footer">
                <form method="POST" action="{% url handle_url %}">
                    {% csrf_token %}
                    <input type="hidden" name="get_add" value=""></input>
                    <button type="button" class="btn btn-block btn-primary js-add-inst-btn" data-url="{% url handle_url %}">
                        <i class="fas fa-plus"></i>
                        Add New
                    </button>
                </form>
            </div>
        </div>
        <!-- Modal for viewing instance -->
        <div class="modal fade" id="modal_form">
            <div class="modal-dialog modal-xl">
                <div class="modal-content">
                    
                </div>
                <!-- /.modal-content -->
            </div>
            <!-- /.modal-dialog -->
        </div>
        <!-- /.modal -->
    </section>
    <!-- /.content -->
  </div>

{% endblock content %}

<!-- Specific Page JS goes HERE  -->
{% block javascripts %}
  
  <!-- jQuery -->
  <script src="/static/assets/plugins/jquery/jquery.min.js"></script>
  <!-- Bootstrap 4 -->
  <script src="/static/assets/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
  <!-- DataTables -->
  <script src="/static/assets/plugins/datatables/jquery.dataTables.min.js"></script>
  <script src="/static/assets/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js"></script>
  <script src="/static/assets/plugins/datatables-responsive/js/dataTables.responsive.min.js"></script>
  <script src="/static/assets/plugins/datatables-responsive/js/responsive.bootstrap4.min.js"></script>
  <!-- AdminLTE App -->
  <script src="/static/assets/js/adminlte.min.js"></script>
  <!-- page script -->
  <script src="/static/assets/js/form_handler.js"></script>
  <script>
    $(function () {
      $("#datatable_feature").DataTable({
        "responsive": true,
        "autoWidth": false,
      });
    });
  </script>

{% endblock javascripts %}

{% comment "Usage" %}
    in views.py just add queryset to context like below
    <Model>.objects.values(<field_values>)
{% endcomment %}

Upvotes: 1

Views: 336

Answers (1)

Abdul Aziz Barkat
Abdul Aziz Barkat

Reputation: 21807

You are not preventing the form from being submitted in your function. You do write return false; but that won't work here as that needs to be done in a fashion like below where somefunction will return false:

<form onsubmit="return somefunction()">

Instead you need to use the event passed to your handler and call preventDefault:

var saveForm = function (event) {
    event.preventDefault(); // prevent form submission
    var form = $(this);
    // Rest of your function
}

Also looking at your javascript you have only attached the on submit handler if your form has one of the classes js-instance-create-form, js-instance-update-form or js-instance-delete-form. But your forms have none of these classes. Add one them to your form:

<form method="POST" action="{% url handle_url %}" class="js-instance-create-form">

Also you attach the event to the forms in this manner:

$("#modal_form form").on("submit", ".js-instance-create-form", saveForm);

But the problem is that the form referred to here doesn't exist yet! Hence your handler never gets attached to anything. Instead simply attach the handler to #modal_form (a parent which already exists) and it should work:

// Create instance
$(".js-add-inst-btn").on("click", loadForm);
$("#modal_form").on("submit", ".js-instance-create-form", saveForm);
  
// Update instance
$(".js-edit-inst-btn").on("click", loadForm);
$("#modal_form").on("submit", ".js-instance-update-form", saveForm);
  
// Delete instance
$(".js-del-inst-btn").on("click", loadForm);
$("#modal_form").on("submit", ".js-instance-delete-form", saveForm);

Upvotes: 1

Related Questions