Django Bootstrap Datepicker In Modal Tutorial

Rendering a Bootstrap Datepicker inside a modal using the bootstrap-datepicker-plus package for Django can sometimes cause some issues based on the order your page loads your scripts. Using a context processor that gives every template access to the form’s media should solve the issue.

I am using Django 3.1 and using Javascript and Ajax to load and submit the form. Here is a quick tutorial:

1. Install Django Bootstrap Datepicker using pip install django-bootstrap-datepicker-plus and follow the package installation instructions

2. Create your form and load the DatePicker widget. In this example I am using a generic Django Form. If you’re using a Model Form, follow the instructions from the package installation link above

from django import forms
from bootstrap_datepicker_plus import DatePickerInput
 
EVENT_TYPE_CHOICES = [
     ("Wedding", "Wedding"),
     ("Bar/Bat Mitzvah", "Bar/Bat Mitzvah"),
     ("Corporate", "Corporate"),
     ("Private Party", "Private Party"),
]
 
class RequestQuoteForm(forms.Form):
       name = name = forms.CharField(max_length=100)
       email = forms.EmailField()
       phone = forms.CharField(max_length=15)
       event_date = forms.DateField(widget=DatePickerInput(format="%m/%d/%Y"), label="Event Date")
       event_type = forms.ChoiceField(choices=EVENT_TYPE_CHOICES, label="Event Type")

3. Create a Context Processor

Inside your app directory create a new file called context_processors.py 

from .forms import RequestQuoteForm

def quote_form_processor(request):
     quote_form = RequestQuoteForm()
     return {'quote_form': quote_form}

4. In your settings.py add the context processor to your TEMPLATES

TEMPLATES = [
        {
            "BACKEND": "django.template.backends.django.DjangoTemplates",
            "DIRS": [str(BASE_DIR.joinpath("templates"))],
            "APP_DIRS": True,
            "OPTIONS": {
                   "context_processors": [
                          "django.template.context_processors.debug",
                          "django.template.context_processors.request",
                          "django.contrib.auth.context_processors.auth",
                          "django.contrib.messages.context_processors.messages",
                          "pages.context_processors.quote_form_processor",
                     ],
               },
         },
   ]

5. Load the media in your base.html template. NOTE: Make sure the form name matches the name you set in your context processor.

{{quote_form.media}}

6. Write your function based view

from django.http import JsonResponse
from django.template.loader import render_to_string
 
def request_quote(request):
    data = dict()
    if request.method == "POST":
         form = RequestQuoteForm(request.POST or None)
         if form.is_valid():
 
             data["html_success_message"] = render_to_string(
                   "pages/includes/partial_quote_submit_success.html", request=request,
              )
             data["form_is_valid"] = True

        else:
             data["form_is_valid"] = False
    else:
         quote_form = RequestQuoteForm()
         data["html_form"] = render_to_string(
               "pages/includes/partial_quote_form.html",
                {"quote_form": quote_form},
                request=request,
                )
return JsonResponse(data)

7. In your static folder create a file named custom.js and load file in the footer of your base.html template

$(function () {

      /* Functions */

      var loadForm = function () {
         var btn = $(this);
         $.ajax({
            url: btn.attr("data-url"),
            type: 'get',
            dataType: 'json',
            beforeSend: function () {
               $("#modal-base .modal-content").html("");
               $("#modal-base").modal("show");
             },
          success:function (data) {
              $("#modal-base .modal-content").html(data.html_form);
          }
      });
   };

var saveForm = function () {
     var form = $(this);
     $.ajax({
         url: form.attr("action"),
         data: form.serialize(),
         type: form.attr("method"),
         dataType: 'json',
         success: function (data) {
            if (data.form_is_valid) {
                $("#modal-base .modal-content").html(data.html_success_message);
            }
            else {
               $("#modal-base .modal-content").html(data.html_form);
            }
       }
    });
    returnfalse;
};


   /* Binding */


   // Request Quote
   $(".js-quote-request").on("click", loadForm);
   $("#modal-base").on("submit", ".js-quote-request-form", saveForm);

});

8. Create your form template and load the form media again

{{quote_form.media}}
<form method="POST" action="{% url 'request_quote' %}" class="js-quote-request-form" id="quoteForm">
     {% csrf_token %}
     <div class="modal-header">
         <h4 class="modal-title">Request a Quote</h4>
      </div>
      <div class="modal-body">
          {% bootstrap_form_errors quote_form %}
          {% bootstrap_form quote_form %}

      </div>
      <div class="modal-footer">
          <button type="button"class="btn btn-default" data-dismiss="modal">Close</button>
          {% bootstrap_button "Schedule" button_type="submit" button_class="btn-primary"%}
     </div>
</form>

9. Create your success template

<div class="modal-header">
      <h4 class="modal-title">Quote Request Sent</h4>
</div>
<div class="modal-body">
        Thank you for submitting your form! We will be in touch soon!

</div>
<div class="modal-footer">
    <button  type="button"class="btn btn-default"data-dismiss="modal">Close</button>
</div>
 

10. Add the modal to your base.html template

<div class="modal fade" id="modal-base">
   <div class="modal-dialog modal-dialog-centered">
       <div class="modal-content">
       </div>
    </div>
</div>

11. Render your modal from any template using a button

<button data-url="{% url 'request_quote' %}" class="btn btn-lg btn-primary js-quote-request">Request a Quote</button>
SHARE

Jared Tangir

Jared Tangir is the Founder and SEO Director of Elevated Audience and a proud alumnus of the Gotch SEO Academy. With a Bachelor of Science in Marketing from the University of Delaware, Jared has seamlessly blended academic knowledge with hands-on expertise. Having transformed his career from a novice to helping clients generate over 7 figures in revenue, Jared’s journey is a testament to his dedication and prowess. With over 5 years of experience in search engine marketing, he is passionate about driving results. Jared specializes in generating leads and sales for clients through SEO, PPC, and Website Design. Recognized for his contributions and results, he is the first-ever recipient of the Gotch SEO VIP Ambassador Award.

Schedule Your FREE Digital Marketing Strategy Call​
What Happens
On A Strategy Call?​
Send Us A Message