How to use django validation with bootstrap tab list

I am trying to use bootstraps tab list with django, Basically i have grouped my fields under several fieldsets in the modelform. in the html template i generate bs nav-pills and tab-control to show the fields. it renders fine. below is the code. However whenever the user leaves a required field empty in a tab which is not active and clicks submit, django cannot put the focus on the required field. the same form works fine without bs tabs. So is there a way for me to be able to use django validation or do I need to write my own js to loop through all required fields and set focus?

========= the model form ================

class PostSellTutorForm(forms.ModelForm):
    class Meta:
        model = SellTutor
        exclude = default_exclude + ['post']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fieldsets = [
                ['Basics', {'comment': 'about the tutor', 'fields': ['english', 'languages', 'years_of_experience', 'primary_occupation', 'message']}],
                ['Cost', {'comment': 'tutor cost', 'fields': ['hourly_rate', 'free_trial', 'free_trial_hours']}],
            ]
        
    def get_fieldsets(self):
        return self.fieldsets


============ the render function ===============
def render_post_form(request, template, form, title, post_id, post_type, partial_save):
    context = {}
    # context['fieldsets'] = form.Fieldsets.value        
    context['form'] = PostSellTutorForm
    context['page_title'] = title
    return render(request, template, context)


=========== the template =======================
{% load static %}
<!-- tutor.html -->

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" crossorigin="anonymous">


    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
    
    <title>Tutor</title>

</head>
<body>
  {% load crispy_forms_tags %}


  <div class="container">
    <h2>Toggleable Pills</h2>
    <br>
    {# Include the hidden fields #}
    {% for hidden in form.hidden_fields %}
    {{ hidden }}
    {% endfor %}
    {# Include the visible fields #}
    {{ form.non_field_errors }}

    {{ form.title.errors }}
    <!-- Nav pills -->
    <ul class="nav nav-pills" role="tablist">
      {% for fieldset_name, fieldset in form.get_fieldsets %}      
      <li class="nav-item">
        <a class="nav-link" data-toggle="pill" href="#{{fieldset_name}}">{{fieldset_name}}</a>
      </li>
      {% endfor %}
    </ul>
  
    <!-- Tab panes -->
      <form method="post" class="tab-content">
        {% for fieldset_name, fieldset in form.get_fieldsets %}
        <div id="{{ fieldset_name }}" class="container tab-pane fade"><br>
          <h3>{{ fieldset_name }}</h3>
          {% csrf_token %}        
          <div class="form-group">
            {% for field in form %}
              {% if field.name in fieldset.fields %}
                <div class="form-group">

                  {{ field |as_crispy_field}}
                </div>
              {% endif %}
            {% endfor %}
          </div>
        </div>
      {% endfor %}
      
      <button type="submit" class="btn btn-primary">Submit</button>
    </form>
  </div>

</body>
</html>
Back to Top