Last active
August 28, 2017 04:26
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
urlpatterns = [ | |
... | |
# Register the JSON URL for the Dependent Field. | |
url(r'^list-artists/$', views.list_artists_by_genre), | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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