我正在构建一个汽车维修估算器,需要创建一个依赖下拉列表,允许用户根据他们选择的品牌从各种模型中进行选择。我可以看到并选择不同的品牌,但看不到不同的型号。我正在使用 Django 框架并将品牌和型号存储在 Postgresql 数据库中
这是我的 ABDjango/templates/models/home.html 文件中的代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Dependent Dropdown in Django</title>
</head>
<body>
<h2>Car Form</h2>
<form method="post" id="modelForm" data-models-url="{% url 'ajax_load_models' %}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$("#id_model").change(function () {
const url = $("#modelForm").attr("data-models-url"); // get the url of the `load_cities` view
const modelId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({
// initialize an AJAX request
url: url, // set the url of the request (= /persons/ajax/load-cities/ )
data: {
'model_id': modelId // 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
/*
let html_data = '<option value="">---------</option>';
data.forEach(function (city) {
html_data += `<option value="${city.id}">${city.name}</option>`
});
console.log(html_data);
$("#id_city").html(html_data);
*/
}
});
});
</script>
</body>
</html>
这是我的 ABDjango/templates/models/model_dropdown_list_options.html 文件中的代码:
<option value="">---------</option>
{% for model in models %}
<option value="{{ model.pk }}">{{ model.name }}</option>
{% endfor %}
这是我的 ABDjango/urls.py 文件中的代码:
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
urlpatterns = [
path('users/', include('autobuddyapp.urls')),
path('admin/', admin.site.urls)
这是我的 autobuddy/models.py 文件中的代码:
from django.db import models
class Make (models.Model):
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class Model(models.Model):
make = models.ForeignKey(Make, on_delete=models.CASCADE)
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class Car(models.Model):
year = models.CharField(max_length=124)
make = models.ForeignKey(Make, on_delete=models.SET_NULL, blank=True, null=True)
model = models.ForeignKey(Model, on_delete=models.SET_NULL, blank=True, null=True)
def __str__(self):
return self.year + " " + str(self.make) + " " + str(self.model)
这是我的 autobuddy/urls.py 文件中的代码:
from django.urls import path
from . import views
urlpatterns = [
path('add/', views.model_create_view, name='model_add'),
path('<int:pk>/', views.model_update_view, name='model_change'),
path('ajax/load-models/', views.load_models, name='ajax_load_models'), # AJAX
]
这里是 autobuddy/views.py:
from django.http import JsonResponse
from django.shortcuts import render, redirect, get_object_or_404
from .forms import ModelCreationForm
from .models import Make, Model, Car
def model_create_view(request):
form = ModelCreationForm()
if request.method == 'POST':
form = ModelCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('model_add')
return render(request, 'models/home.html', {'form': form})
def model_update_view(request, pk):
car = get_object_or_404(Car, pk=pk)
form = ModelCreationForm(instance=car)
if request.method == 'POST':
form = ModelCreationForm(request.POST, instance=car)
if form.is_valid():
form.save()
return redirect('model_change', pk=pk)
return render(request, 'models/home.html', {'form': form})
# AJAX
def load_models(request):
model_id = request.GET.get('model_id')
models = Model.objects.filter(model_id = model_id).all()
return render(request, 'models/model_dropdown_list_options.html', {'models': models})
# return JsonResponse(list(cities.values('id', 'name')), safe=False)
Autobuddy/forms.py
from django import forms
from autobuddyapp.models import Make, Model, Car
class ModelCreationForm(forms.ModelForm):
class Meta:
model = Car
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['model'].queryset = Model.objects.none()
if 'make' in self.data:
try:
make_id = int(self.data.get('make'))
self.fields['model'].queryset = Model.objects.filter(make_id=make_id).order_by('name')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and fallback to empty City queryset
elif self.instance.pk:
self.fields['model'].queryset = self.instance.model.make_set.order_by('name')
第一个问题就在脚本的第一行:
<script>
$("#id_model").change(function () {
...
您正试图在错误的选择上捕获更改事件,它应该在
id_make
上。响应方法和您尝试更新选择器的方式也存在问题。
Response 应该是一个 JSON 对象。要更新选择器,我们需要创建
options
并添加到特定元素,在本例中为 id_model
。 (此外,我们需要在再次填充之前清除它)
views.py
def load_models(request):
make_id = request.GET.get('make_id')
models = list(Model.objects.filter(make__id = make_id).values())
return JsonResponse({'models': models})
template.html
<script>
$("#id_make").change(function () {
const url = $("#modelForm").attr("data-models-url"); // get the url of the `load_cities` view
const makeId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({
// initialize an AJAX request
url: url, // set the url of the request (= /persons/ajax/load-cities/ )
data: {
'make_id': makeId // add the country id to the GET parameters
},
success: function (data) { // `data` is the return of the `load_cities` view function
$('#id_model').empty();
for (let i = 0; i < data.models.length; i++) {
var option = $('<option/>');
option.attr({ 'value': data.models[i].id }).text(data.models[i].name);
$('#id_model').append(option);
}
}
});
});
</script>
其他一切,保持不变。