How do I insert a django form in twitter-bootstrap modal window?

后端 未结 2 1537
余生分开走
余生分开走 2020-11-27 11:02

Someone has asked the exact same question in April, without any answer. But since he provided too little information; the question was abandoned.

I have the same pro

相关标签:
2条回答
  • 2020-11-27 11:38

    Unless you need to use the contact form outside of the modal, this should work for you. If you do need to use it elsewhere, maintain two versions (one modal, one not). Also, a tip - give django-crispy-forms a lookover - it helps you render forms with twitter-bootstrap classes.

    contact.html:

    <div class="modal hide" id="contactModal">
    <form class="well" method="post" action="/contact/edit/{{ item.id }}">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">×</button>
        <h3>Editing Contact</h3>
      </div>
      <div class="modal-body">
           {% csrf_token %}
           {{form.as_p}}
      </div>
      <div class="modal-footer">
           <input class="btn btn-primary" type="submit" value="Save" />
           <input name="cancel" class="btn" type="submit" value="Cancel"/>
      </div>
    </form>
    </div>
    

    main_page.html

    <html>
    ...
    
    <a data-toggle="modal" href="#contactModal">Edit Contact</a>
    
    {% include "contact.html" %}
    
    ...
    </html>
    

    Edit:

    Ok, so now that I know that you have potentially multiple forms, it's probably a bad idea to render each form hidden within the html. You probably want to go to an ajax-y version, and load each form on demand. I'm assuming here that on form submit, the whole page will reload. If you want to asynchronously submit the form, there are answers elsewhere.

    We'll start by re-defining the contact.html fragment. It should render within a modal, and contain all the markup necessary to play nice with the modal. The contact view that you have originally is fine - except that if the form is invalid, you'll end up rendering the contact.html and nothing else.

    <form class="well contact-form" method="post" action="/contact/edit/{{ item.id }}">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">×</button>
        <h3>Editing Contact</h3>
      </div>
      <div class="modal-body">
           {% csrf_token %}
           {{form.as_p}} <!-- {{form|crispy}} if you use django-crispy-forms -->
      </div>
      <div class="modal-footer">
           <input class="btn btn-primary" type="submit" value="Save" />
           <input name="cancel" class="btn" type="submit" value="Cancel"/>
      </div>
    </form>
    

    And now, your main_page.html:

    <html>
    .. snip ..
    
    <a class="contact" href="#" data-form="/contact/edit/{{ item.id }}" title="Edit">edit</a>
    <a class="contact" href="#" data-form="/contact/edit/{{ item.id }}" title="Edit">edit</a>
    <a class="contact" href="#" data-form="/contact/edit/{{ item.id }}" title="Edit">edit</a>
    
    <div class="modal hide" id="contactModal">
    </div>
    
    <script>
        $(".contact").click(function(ev) { // for each edit contact url
            ev.preventDefault(); // prevent navigation
            var url = $(this).data("form"); // get the contact form url
            $("#contactModal").load(url, function() { // load the url into the modal
                $(this).modal('show'); // display the modal on url load
            });
            return false; // prevent the click propagation
        });
    
        $('.contact-form').live('submit', function() {
            $.ajax({ 
                type: $(this).attr('method'), 
                url: this.action, 
                data: $(this).serialize(),
                context: this,
                success: function(data, status) {
                    $('#contactModal').html(data);
                }
            });
            return false;
        });
    </script>
    
    .. snip ..
    </html>
    

    This is all untested, but it should give you a good place to start/iterate from.

    0 讨论(0)
  • 2020-11-27 11:57

    I was having the same problem when I encounter this post. I tried this solution but it wasn't really working for me (but it gave me direction). I came up with a solution that does work for me but, it feels hacky and I would like to receive some pointers on how to do it better.

    The problem is the same: Show a form inside twitter boostrap modal and django form (edit/add model for me using django generic form views)

    So what I did:

    main.html

    <script type="text/javascript">
        function genericLoadDialog(form_selector, dialog_selector, matchString){
            $.ajax({
                url: $(form_selector).attr('action'),
                type: 'POST',
                data:  $(form_selector).serialize(),
                success: function(data, textStatus, jqXHR){
                    if(data.match(matchString)){
                    // We got errors in form
                        $(dialog_selector).html(data).modal('show');
                                return false;
                    }
                            $(dialog_selector).modal('hide');
                },
            })
        }
    </script>
    
    <body>
    <div class="modal hide" id="{{ editor_dialog_id }}"></div>
    <a data-toggle="modal" href="#{{ editor_dialog_id }}" onclick="$('#{{ editor_dialog_id }}').load('/create/form');">Title</a>
    <body>
    

    editor.html

    <form id="{{ editor_form_id }}" action="{{ submit_url }}" method="POST">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal">×</button>
            <h3>Modal header</h3>
        </div>
        <div class="modal-body" id="editor-dialog-body">
            {% if not form.is_valid %}
                <div class='hide'>invalid_form</div>
            {% endif %}
            {% csrf_token %}
            {{ form.as_p }}
        </div>
        <div class="modal-footer">
           <a href="#" class="btn" data-dismiss="modal">Cancel</a>
           <a href="#" data-toggle="modal" class="btn btn-primary" onclick="genericLoadDialog('#{{ editor_form_id }}', '#{{ editor_dialog_id }}', null, 'invalid_form');">Save</a>
        </div>
    </form>
    

    So the flow is this:

    • click on the tag loads the form from the create form url into the modal div
    • click the save button in modal (submit) which triggers the genericLoadDialog function. This loads makes a POST request to the create form url with data collected from the form
    • If the form is invalid it reloads the modal html and shows the error fields, else closes the modal and django should save/redirect (I use get_success_url method in django form view but not working for me for some reason. It does save the object)

    I'm uncomfortable with the way I check if the form is valid or not in genericLoadDialog, if someone has a better idea would be nice.

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