Reputation: 494
Django noob
I am currently attempting to implement a dependent drop down list for car models - manufactures I am following this tutorial
I have the form displaying properly but the issue I am facing is if I select a manufacture no models are displayed.
I have spent a bunch of time attempting to solve this and I am out of ideas
All feedback welcome!
forms.py
from blog.models import Post, Manufactures, Models
class PostForm(ModelForm):
class Meta:
model = Post
fields = 'title', 'manufacture', 'model', 'content', 'image', 'aspiration'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['model'].queryset = Models.objects.none()
models.py
class Manufactures(models.Model):
manufacture_id = models.AutoField(primary_key=True)
manufacture = models.CharField(max_length=55)
def __str__(self):
return self.manufacture
def get_absolute_url(self):
return reverse('db-manufactures', kwargs={'pk': self.pk})
class Models(models.Model):
model_id = models.AutoField(primary_key=True)
model = models.CharField(max_length=55)
model_manufacture = models.ForeignKey(Manufactures, on_delete=models.CASCADE)
def __str__(self):
return self.model
def get_absolute_url(self):
return reverse('blog-models', kwargs={'pk': self.pk})
Views.py
def loadModels(request):
manufacture_id = request.GET.get('model_manufacture')
models = Models.objects.filter(manufacture_id = manufacture_id)
return render(request, 'model_dropdown_list.html', {'models': models})
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
form_class = PostForm
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def save(self, *args, **kwargs):
super(Post,self).save(*args, **kwargs)
model_dropdown_list.html
<option value="">---------</option>
{% for model in models %}
<option value="{{ model.pk }}">{{ model.name }}</option>
{% endfor %}
post_form.html
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="post" id="modelForm" data-models-url="{% url 'ajax' %}" novalidate>
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Create Post</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$("#id_manufacture").change(function () {
var url = $("#PostForm").attr("data-models-url"); // get the url of the `load_cities` view
var manufactureId = $(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: {
'manufacture': manufactureID // add the country id to the GET parameters
},
success: function (data) { // `data` is the return of the `load_cities` view function
$("#id_model").html(data); // replace the contents of the city input with the data that came from the server
}
});
});
</script>
{% endblock content %}
urls.py
urlpatterns = [
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('ajax/load-models', views.loadModels, name='ajax')
]
Update
The error was in my post_form.html I had use a lowercase d and not an uppercase
<script>
$("#id_manufacture").change(function () {
var url = $("#PostForm").attr("data-models-url");
var manufactureId = $(this).val(); !!!lowercase "d" on manufactureId
$.ajax({
url: url,
data: {
'manufacture_id': manufactureID !!!uppercase "D"
},
success: function (data) {
$("#id_model").html(data);
}
});
});
New Issue
It seems to be making the correct call and is grabbing the proper id except it is behaving strangely. When I select a manufacture it runs the request once. If I then change my mind and select a different manufacture it runs the call twice(with the correct id) and so on.
except when on the page after you select a manufacture the model drop down is empty
Solution
def loadModels(request):
model_manufacture_id = request.GET.get('model_manufacture')
models = Models.objects.filter(model_manufacture_id=model_manufacture_id) #orderby?
return render(request, 'blog/model_dropdown_list.html', {'models': models})
Upvotes: 0
Views: 196
Reputation: 348
This looks like in the Tutorial, but i can't say 100% because your urls.py
is missing. Did you check developer console? Try to console.log(manufactureId)
and console.log(url)
to check if you have the right data needed
also what i can see -> your model dont have a property called name
, it is called model
In your Models class - so you need to get model.model
Instead of model.name
in model_dropdown_list.html
class Models(models.Model):
model_id = models.AutoField(primary_key=True)
--> model = models.CharField(max_length=55)
model_manufacture = models.ForeignKey(Manufactures, on_delete=models.CASCADE)
def __str__(self):
return self.model
def get_absolute_url(self):
return reverse('blog-models', kwargs={'pk': self.pk})
The template has to look like this:
<option value="">---------</option>
{% for model in models %}
<option value="{{ model.pk }}">{{ model.model }}</option>
{% endfor %}
PS: what i can See, you want to access your form with $("#PostForm")
but it’s Id is modelForm
- please check your namings :)
Upvotes: 1