Form with large number of select choices very slow

  1. In this edit_shift.html form I have 2 select fields, ‘site’ and ‘user’, with both >300 choices. This slows down the loading time of the form to +/- 12 sec. Is there an easy way to improve this? In de Django admin the admin form is lightning fast. Note: this is on my local development server.

  2. Would there be better ways to select from a large nummer of choices other the a select field? EG a pop-up list?

{% extends 'base.html' %}

{% load custom_filters %}

{% block content %}

    {% load static %}

    {% block additional_css %}
        <link rel="stylesheet" type="text/css" href="{% static 'css/form.css' %}">
    {% endblock %}

    <form class="form bg" method="post">
        <button type="submit" class="btn btn-primary custom-button align-right">Save</button>
        {% csrf_token %}

        <div class="form-group">
            <label for="status">Status</label>
            <select class="form-select small-size select-value form-select-sm" id="status" name="status">
                {% for choice in form.status.field.choices %}
                    <option value="{{ choice.0 }}"
                            {% if choice.0 == shift.status.id %}selected{% endif %}>{{ choice.1 }}</option>
                {% endfor %}
            </select>
        </div>

        <div class="form-group">
            <label for="shift_title">Title</label>
            <input type="text" class="form-control form-control-sm shift-title" id="shift_title" name="shift_title"
                   value="{{ shift.shift_title }}">
        </div>

        <div class="form-group">
            <label for="job">Job</label>
            <select class="form-select form-select-sm small-size select-value" id="job" name="job">
                {% for choice in form.job.field.choices %}
                    <option value="{{ choice.0 }}"
                            {% if choice.0 == shift.job.id %}selected{% endif %}>{{ choice.1 }}</option>
                {% endfor %}
            </select>
        </div>


        <div class="form-group">
            <label for="start_date">Start Date / {{ shift.start_date|date:'l' }}</label>
            <input type="date" class="form-control form-control-sm small-size" id="start_date" name="start_date"
                   value="{{ shift.start_date|date:'Y-m-d' }}">
        </div>


        <div class="form-group">
            <label for="start_time">Start Time</label>
            <input type="time" class="form-control form-control-sm small-size" id="start_time" name="start_time"
                   value="{{ shift.start_time }}">
        </div>

        <div class="form-group">
            <label for="end_time">End Time</label>
            <input type="time" class="form-control form-control-sm small-size" id="end_time" name="end_time"
                   value="{{ shift.end_time }}">
        </div>

        <div class="form-group">
            <label for="site">Site</label>
            <select class="form-select form-select-sm select-value" id="site" name="site">
                {% for site_instance in sites %}
                    <option value="{{ site_instance.id }}" data-phone="{{ site_instance.phone }}"
                            {% if site_instance.id == shift.site.id %}selected{% endif %}>
                        {{ site_instance.site_name }}  <!-- Assuming the site model has a name field -->
                    </option>
                {% endfor %}
            </select>
        </div>

        <div class="contactdetails">
            <b>Tel:</b> <span id="sitePhone">{{ shift.site.phone }}</span>
        </div>

        <div class="form-group">
            <label for="user">User</label>
            <select class="form-select form-select-sm select-value" id="user" name="user">
                <option value="" {% if not shift.user %}selected{% endif %}>OPEN</option>
                {% for user_instance in users %}
                    <option value="{{ user_instance.id }}"
                            data-email="{{ user_instance.email }}"
                            data-phone="{{ user_instance.user_profile.phone }}"
                            {% if user_instance.id == shift.user.id %}selected{% endif %}>
                        {{ user_instance|user_info_with_current_job|safe }}
                    </option>
                {% endfor %}
            </select>
        </div>

        <div class="contactdetails">
            <b>Email:</b> <a href="mailto:{{ shift.user.email }}" id="userEmail">{{ shift.user.email }}</a> /
            <b>Tel:</b> <span id="userPhone">{{ shift.user.user_profile.phone }}</span>
        </div>


        <div class="form-group">
            <label for="user_notes">User Notes</label>
            <textarea class="form-control form-control-sm" id="user_notes"
                      name="user_notes">{{ shift.user_notes }}</textarea>
        </div>

        <div class="form-group">
            <label for="customer_notes">Customer Notes</label>
            <textarea class="form-control form-control-sm" id="customer_notes"
                      name="customer_notes">{{ shift.customer_notes }}</textarea>
        </div>

        <div class="form-group">
            <label for="admin_notes">Admin Notes</label>
            <textarea class="form-control form-control-sm" id="admin_notes"
                      name="admin_notes">{{ shift.admin_notes }}</textarea>
        </div>

        <!--SUBMIT BUTTON IS AT THE TOP-->

    </form>

{% endblock %}

Yes. Take a look at Django-Select2. It, or something like it, is probably your best bet.

The other thing you want to do is ensure you’re not encountering something like an N+1 query situation as you’re trying to iterate over the options.

1 Like

Thanks Ken. Select2 makes loading lightning fast without noticeable delay! I really appreciate the effort you put in maintaining this forum! Learned so much.

Is it reasonable to use django-select2 also for selects with 100 000 options? Or would you recommend another solution?

If you can allocate a sufficiently large cache for it, I see no reason why not.

I’ve never looked for solutions at that scale, so I don’t know what other options would be available.

Thank you for the quick response

Hi Lucsemer, Select2 has the option to start with a search field and begin typing reduces the options. What do you need to select? names? products? You could consider to categorize them in alphabet, product group, location etc. Then you can use that info in two or more search boxes. When selecting a devined first group use that selection as a filter for the second selection. Adding more steps as needed.

Hi perry7t, I used select2. However, I think, the cache is needed also in this case, where only search field is present.