I am trying to implement a dependent dropdown. Vitor Freitas did this in his blog and I am basically following his solution. (A really cool blog with clear code which helped me a lot of times).
I have adopted it to my pages but it stuck exactly where the dropdown should be restricted. I am pretty sure that I messed up with the foreign key or with Ajax/javascript (as I have no clue about ajax+javascript.)
Maybe you see my 'basic' error and can help me. Would be thankful.
models.py
class Country(models.Model):
name = models.CharField(max_length=3)
def __str__(self):
return self.name
class Provider(models.Model):
country = models.ForeignKey(Country, on_delete=models.CASCADE)
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class CustomerSubsidiary(models.Model):
subCountry = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True)
subName = models.CharField(max_length=50, blank=True)
urls.py
urlpatterns = [
path('test', views.CustomerSubsidiaryListView.as_view(), name='CustomerSubsidiary_changelist'),
path('test/add/', views.CustomerSubsidiaryCreateView.as_view(), name='CustomerSubsidiary_add'),
path('test/<int:pk>/', views.CustomerSubsidiaryUpdateView.as_view(), name='CustomerSubsidiary_change'),
path('ajax/load-provider/', views.load_provider, name='ajax_load_provider'),
]
views.py
def load_provider(request):
country_id = request.GET.get('country')
provider = Provider.objects.filter(country_id=country_id).order_by('name')
return render(request, 'Customer/city_dropdown_list_options.html', {'provider': provider})
providerForm
class ProviderForm(forms.ModelForm):
class Meta:
model = CustomerSubsidiary
fields = ('subName', 'subCountry', 'provider')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['provider'].queryset = Provider.objects.none()
customersubsidiary_form.html
{% extends 'base.html' %}
{% block content %}
<h2>Provider Form</h2>
<form method="post" id="providerForm" data-provider-url="{% url 'ajax_load_provider' %}" novalidate>
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Save</button>
<a href="{% url 'CustomerSubsidiary_changelist' %}">Nevermind</a>
</form>
<script>
$("#id_country").change(function () {
var url = $("#providerForm").attr("data-provider-url");
var countryId = $(this).val();
$.ajax({
url: url,
data: {
'country': countryId
},
success: function (data) {
$("#id_provider").html(data);
}
});
});
</script>
{% endblock %}
The jquery is loaded in the base.html.
city_dropdown_list_options.html
<option value="">-------</option>
{% for providers in provider %}
<option value="{{ providers.pk }}">{{ providers.name }}</option>
{% endfor %}
I saw in the source code of the page that the names for the Ids where wrong that means they did not match to views.py.
In views.py it should be:
def load_provider(request):
country_id = request.GET.get('subCountry') #<-- change country to subCountry, that means the attribute name of the original class
In the ajax-script change the id to #id_subCountry and change country to subCountry:
<script>
$("#id_subCountry").change(function () {
var url = $("#providerForm").attr("data-provider-url"); // get the url of the `load_cities` view
var subCountryId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= localhost:8000/hr/ajax/load-cities/)
data: {
'subCountry': subCountryId // add the country id to the GET parameters
},
success: function (data) { // `data` is the return of the `load_cities` view function
$("#id_provider").html(data); // replace the contents of the city input with the data that came from the server
}
});
});
</script>