Search code examples
pythondjangodjango-viewsdjango-templatesbootstrap-modal

should django modal have a separate view?


I am working on an application that has a page with a table that is a list of users. Each user has a button which pops up a modal that does something. I am trying to create the modal that will get the user information when the button in clicked, additionally, I need in that modal some logic based on the user information and some more data. I am thinking that it makes sense to create a separate view for it but since each view must be on a different url, the concept of the modal does not makes sense (for me), because I want it to be on the same url.

  • Is it possible to have a modal with a different view that will have a separate logic? Since the modal is included in the template and it is basically just one template, then, can one template have 2 views?

  • What is the best way to implement the modal using django? And how to pass data to it, I need the data from the row that was selected + some more data from db. I have the data from the context but manipulating that using JQuery for me is a bad idea - because I am using a python session on the backend that communicates with another api, so when user clickes the modal save button, a python request needs to be done, this means I need a view for it.

Here is my try

Modal
{% block modal %}
{% load static %}
{% load authorization_tags %}
<!-- Modal -->
<div class="modal fade" id="{{modal_id}}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
      <div class="row">
          <div class="col-lg-5">
            <img class="d-block w-100"
              src="{% static 'app/assets/images/security-shield1.png' %}"
              alt="First slide">
              Use access control to deauthorize user
          </div>
          <div class="col-lg-7">
            <h2 class="h2-responsive product-name">
              <strong>{{user.real_name}}</strong>
            </h2>
            <h4 class="h4-responsive">
              <span class="green-text">
                {{user.username}}
              </span>
              </span>
            </h4>
            <div class="accordion md-accordion" id="accordion1" role="tablist" aria-multiselectable="true">
              <div class="card">
                <div class="card-header" role="tab" id="heading2">
                  <a data-toggle="collapse" data-parent="#accordion1" href="#collapse1" aria-expanded="true"
                    aria-controls="collapse1">
                    <h5 class="mb-0">
                      Current Authorizations <i class="fas fa-angle-down rotate-icon"></i>
                    </h5>
                  </a>
                </div>

                <div id="collapse1" class="collapse show" role="tabpanel" aria-labelledby="heading1"
                  data-parent="#accordion1">
                  <div class="card-body">

                  {% for right in people_rights|user_active_rights:user.id %}
                    {{right.room}}
                  {% endfor %}

                  </div>
                </div>

              </div>
            </div>
            <div class="accordion md-accordion" id="accordion2" role="tablist" aria-multiselectable="true">
              <div class="card">
                <div class="card-header" role="tab" id="heading2">
                  <a data-toggle="collapse" data-parent="#accordion2" href="#collapse2" aria-expanded="true"
                    aria-controls="collapse2">
                    <h5 class="mb-0">
                      Available Authorizations <i class="fas fa-angle-down rotate-icon"></i>
                    </h5>
                  </a>
                </div>

                <div id="collapse2" class="collapse show" role="tabpanel" aria-labelledby="heading2"
                  data-parent="#accordion2">
                  <div class="card-body">
                  </div>
                </div>
              </div>
            </div>
            <div class="card-body">
              
              <div class="text-center">
                <button type="button" class="btn btn-lg" data-dismiss="modal"><span>Close</span></button>
                <button class="btn btn-lg"><span>Authorize</span></button>
              </div>
            </div>
          </div>
        </div>
    </div>  
  </div>
</div>
{% endblock modal %}

a piece of table and the modal included in the same template

{% include 'app/admin/users/user_authorize.html' with modal_id="authModal" user=row areas=areas rooms=rooms people_rights=people_rights %}


{%if row.empno %}
  <td class="txt-oflo">{{ row.empno }}</td>
{% else %}
  <td class="txt-oflo">-</td>
{% endif %}
  <td>
{% with "#"|add:row.id as buttonId %}
  <button id={{buttonId}} class="btn btn-lg" data-toggle="modal" data-target="#authModal">
      <span>Authorize</span>
  </button>
{% endwith %}
  </td>
</tr>


Solution

  • You can try the following steps to solve the issue.

    1. Create a separate view for the modal on a separate url.
    2. Take the modal data out of this html file and place it in another html file. The empty modal in the original html should look something like this.
    <div id="SampleTable" class="modal fade" tabindex="-1" role="dialog">
                            <div class="modal-dialog" role="document">
                              <div class="modal-content">
                                <div class="modal-header">
                                  <h5 class="modal-title">sample title</h5>
                                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                                    <span aria-hidden="true">&times;</span>
                                  </button>
                                </div>
                                <div class="modal-body" id="sample_datatable">
    
                                </div>
                                <div class="modal-footer">
                                  <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                                </div>
                              </div>
                            </div>
    
    1. Render that new html from the new view that was created. The ajax request that will be activated from the button that gives us the modal table might look something like this.
    @app.route('/sample_data', methods=['GET', 'POST'])
    def modal_table():
        try:
            data = request.args.get('arg')
            database_data = Table.query.filter(Table.data == data).all()
            result_dict = [u.__dict__ for u in database_data]
        except Exception as e:
            traceback.print_exc()
        return render_template('modal_table.html', data=enumerate(result_dict))
    
    1. The button in the original html that results in the modal table should be configured in a way using ajax requests that it renders data from the new html into the old modal data like this.
    function get_sample_data() {
            $.ajax({
                url:"/sample_data", //the page containing python script
                type: "GET", //request type,
                data: {},
                async:true,
                beforeSend: function(){
                        $('#sample_datatable').html('Loading..');
                      },
                success:function(result){
                    $('#sample_datatable').html(result);
                }
            });
    }
    

    You can call this javascript function from the button that is supposed to show the modal table.