查询集更改为none或subset时出现Django表单错误

问题描述 投票:0回答:1

我正在 Django 中使用 htmx 开发一个依赖下拉列表。由于数据集非常大,我不想在一开始就加载所有数据,而只是使用 htmx 动态加载所需的数据。当我将查询集设置为 Model.objects.all() 时,表单工作正常,但由于最初加载需要很长时间,所以我将查询集更改为 Models.objects.none() 或 Models.object.all()[: xx] 因此没有数据或数据最少。该表单按预期工作,并且依赖的下拉菜单工作得很好,但是当我提交表单时,出现错误“选择一个有效的选择。该选择不是可用的选择之一。” 我的问题是 .all() 返回的对象是否与 .none() 或 all()[:xx] 不同?如果不是的话是什么原因导致错误?我花了几个小时试图找出错误的原因,但无济于事。我想知道导致错误的原因。

这是 models.py

class Province(models.Model):
province_code = models.CharField(max_length=2)
province_name = models.CharField(max_length=30) 
class City(models.Model):
    province = models.ForeignKey(Province,on_delete=models.CASCADE)
city_code = models.CharField(max_length=2)
city_name = models.CharField(max_length=30) 
class Address(models.Model):
province = models.ForeignKey(Province, on_delete=models.CASCADE)
city = models.ForeignKey(City, on_delete=models.CASCADE)
address = models.CharField(max_length=50) 
这是表格.py

class AddressForm(ModelForm):
class Meta:
model = Addreess
fields ='__all__'
widgets = {
"province": form.Select(
attrs={
"hx-get":"import/load-city/",
"hx-target":"#city",
"hx-trigger":"change",
"hx-swap":"innerHTML",
}
),
"city": form.Select(
attrs={
"id":"city"
 }
),
}

` def __init__(self, *args, **kwargs):`
     `super(AddressForm, self).__init__(*args,**kwargs)`
     `self.fields["province"].queryset = Province.objects.all()`
     `self.fields["city"].queryset = City.objects.all()  ## comment: error if .none() or .all()[:xx]

` 这是views.py

class AddressCreateView(CreateView):
model = Address
form_class = AddressForm
template_name = 'address_create.html'
success_url ='/'

class LoadCityView(View):
def get(self,request):
if request.GET.get("province"):
province = request.GET.get("province")
else:
province=None
cities = City.objects.filter(province=province) 
context = {"cities":cities}
return render(request,"load_cities.html",context)

这是 urls.py

urlpatterns = [
path('address-create/',AddressCreateView.as_view(),name='address-create'),
path('load-city/',LoadCityView.as_view(),name='load-city'),
]

这是模板

地址_创建.html

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="post>
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://unpkg.com/[email protected]"></script>
<script>
document.body.addEventListener('htmx:configRequest', (event) =>
{
event.detail.headers['X-CSRFToken']='{{csrf_token}}';
})
</script>
</body>
</html> 
load_cities.html
<option value="">------------</option>
{% for city in cities %}
<option value="{{city.id}}">{{city.city_code}} {{city.city_name}}</option>
{% endfor %}

django-forms django-queryset htmx
1个回答
0
投票

不要设置查询集,将

.choices
设置为空,这将阻止 rendering 项目,但仍然可以正确进行验证:

class AddressForm(ModelForm):
    class Meta:
        model = Addreess
        fields ='__all__'
        widgets = {
            'province': form.Select(
                attrs={
                    'hx-get':'import/load-city/',
                    'hx-target':'#city',
                    'hx-trigger':'change',
                    'hx-swap':'innerHTML',
                }
            ),
            'city': form.Select(
                attrs={
                    'id':'city'
                }
            ),
         }

     def __init__(self, *args, **kwargs):
         super().__init__(*args,**kwargs)
         self.fields['city'].choices = []

这仍然会使用包含所有项目的

.queryset
来验证该项目,从而会对数据库进行 filtered 查询,但忽略 rendering 这些选择。

您正在尝试做的事情,使用 AJAX 的延迟加载项目已包装在名为

django-select2
 [readthedocs.io] 的包中,最好不要重新发明轮子,并让包处理这个问题.


注意:自 PEP-3135 [pep] 起,如果第一个参数是定义方法的类,第二个参数是方法,则无需带参数调用

super(…)
函数的第一个参数(通常为
self
)。

© www.soinside.com 2019 - 2024. All rights reserved.