Skip to content

Instantly share code, notes, and snippets.

@ranelpadon
Last active August 28, 2017 04:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ranelpadon/acbb99ed5376b60f840d1fbe0b4f17c2 to your computer and use it in GitHub Desktop.
Save ranelpadon/acbb99ed5376b60f840d1fbe0b4f17c2 to your computer and use it in GitHub Desktop.
Update the select list field B based on the currently selected option in select list field A. For example, when you select a particular Music Genre, only the related Artists should show. Other common use cases/relationships: Country/Cities, Organization/Members, Company/Contact Persons, Brand/Products, etc.
// Workflow (Genre is the Parent Field, Artist is the Dependent Field):
// 1. user interacts w/ Genre select list widget via JS script.
// 2. JS script fetches the new Artist list in views.py
// 3. JSON response will be used as the new values/options for the Artist select list widget.
(function($) {
$(function() {
// Artist's select option values will depend on
// the Genre's selected option.
var $genreSelectWidget = $('#id_genre');
var $artistSelectWidget = $('#id_artist');
var artistSelectWidgetInitial = $artistSelectWidget.val()
// Adjust Artists based on the selected Genre.
function adjustArtistOptions(preSelectedOption) {
var selectedGenre = $genreSelectWidget.find(':selected').text();
$.getJSON('/list-artists/?genre=' + selectedGenre, function(data) {
var $artistNonEmptyOptions = $artistSelectWidget.find('option:not(:first)');
$artistNonEmptyOptions.remove();
// Rebuild the options.
var artistOptions = []
$.each(data, function(dataIndex, artist) {
var artistOption = $('<option>', {
value: artist.id,
text : artist.name
});
artistOptions.push(artistOption);
});
$artistSelectWidget.append(artistOptions);
// On page load.
if (preSelectedOption) {
$artistSelectWidget.val(preSelectedOption);
}
// Optional behavior.
// Auto-select the first non-empty option for better UX.
else {
$artistSelectWidget.find('option:nth-child(2)').prop('selected', true);
}
});
}
// On page load, update the options and auto-select the previously saved option in db,
// or the one set as initial value.
adjustArtistOptions(artistSelectWidgetInitial);
// As the user starts interacting with the Genre select list field,
// refresh the Artist select list field options accordingly.
$genreSelectWidget.change(function() {
adjustArtistOptions();
});
});
})(django.jQuery);
urlpatterns = [
...
# Register the JSON URL for the Dependent Field.
url(r'^list-artists/$', views.list_artists_by_genre),
]
from django.http import JsonResponse
# The Dependent Model.
from .models import Artist
def list_artists_by_genre(request):
"""
Returns the list of Artist's `id` and `name` fields in JSON format
given the specified "Genre" as query parameter.
Sample Request: /list-artists/?genre=rock
"""
genre = request.GET.get('genre', '')
# The query param is used to filter the Dependent Model.
# Hence, it could be any field, including ForeignKeys.
artists = Artist.objects.filter(genre__name__iexact=genre)
data = [{'id': artist.id, 'name': artist.name} for artist in artists]
# For Django 1.6 or older:
# import json
# from django.http import HttpResponse
# return HttpResponse(json.dumps(data), content_type='application/json')
return JsonResponse(data, safe=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment