我有一个用户可以填写的表单。我想要的是一个依赖的下拉菜单,这样当选择路由器(ce_hostname)时,该路由器的端口(l2_interfaces)可以从第二个下拉菜单(ce_wan_port)中选择。端口列表以json列表的形式存储在路由器中,路由器以外键的形式存储。
models.py
#Unique order. Top of heirachy tree
class Order(models.Model):
order_name = models.CharField(max_length=100, unique=True)#, null=True, blank=True) #Unique name of order
#For CE router definition. Required for all orders.
class Ce_Base(models.Model):
ce_hostname = models.CharField(max_length=15, validators=[CE_HOSTNAME_REGEX], verbose_name="CE Hostname", help_text="Hostname of router.")
l2_interfaces = JSONField(null=True) #Layer 2 interfaces
#For defining WAN links
class Ce_Pe(models.Model):
order_reference = models.ForeignKey(Order, null=True, on_delete=models.CASCADE) #Order reference
ce_hostname = models.ForeignKey(Ce_Base, null=True, on_delete=models.CASCADE, verbose_name="CE Hostname", help_text="Hostname of CE router.")
ce_wan_port = models.CharField(max_length=500, null=True, blank=True)
对于我的下拉菜单,ce_wan_port应该是l2_interfaces的下拉菜单,在选择了ce_hostname之后出现。
示例l2_interfaces data
[
"Gi0/0/0",
"Gi0/0/1",
"Gi0/0/2"
]
forms.py
class Ce_PeForm(ModelForm):
class Meta:
model = Ce_Pe
fields = ['ce_hostname', 'ce_wan_port',]
def __init__(self, *args, order_reference, **kwargs):
super().__init__(*args, **kwargs)
order_id = str(order_reference.id)
self.fields['ce_hostname'].queryset = Ce_Base.objects.filter(order_reference=order_id,)
当前正在过滤相同顺序的ce_hostname对象。
views.py
@login_required
def addCe_Pe(request, pk_test):
order = Order.objects.get(id=pk_test)
ce_pe_form = Ce_PeForm(order_reference=order)
if request.method == 'POST':
ce_pe_form = Ce_PeForm(request.POST, order_reference=order)
ce_pe_form.instance.order_reference = order
if ce_pe_form.is_valid():
ce_pe_form.save()
return redirect('/')
context = {'ce_pe_form':ce_pe_form}
return render(request, 'orchestration/ce_pe_form.html', context)
我试着发送ce_hostname变量,但这对我来说没有意义,因为它可以改变每次用户改变下拉菜单,而不仅仅是在类init或post。
这是我的html
{% extends "orchestration/base.html" %}
{% load static %}
{%load crispy_forms_tags %}
{% block content %}
<h1>CE PE WAN Link Definition</h1>
<div class="row">
<div class="col-md-15">
<div class="card card-body">
<form action="" method="POST">
{% csrf_token %}
{{ce_pe_form|crispy}}
<p></p>
<input type="submit" name="Submit">
</form>
</div>
</div>
</div>
编辑:
我有了一点进展,但还是想不出如何把这些拼凑起来。
在我的views.py中,我能够获得我想要的对象并将它们打印出来。从这里,我可以看到如何从选中的下拉列表中获得正确的列表。
def addCe_Pe(request, pk_test):
order = Order.objects.get(id=pk_test)
ce_pe_form = Ce_PeForm(order_reference=order)
if request.method == 'POST':
ce_pe_form = Ce_PeForm(request.POST, order_reference=order)
ce_hostname = request.POST.get('ce_hostname')
ce_dropdown = Ce_Base.objects.get(id=ce_hostname)
print(ce_dropdown.l2_interfaces)
在我的forms.py中,我可以覆盖这些选择。我想这就是我想要做的,但我不确定如何动态地做到这一点,因为用户从下拉菜单中选择ce_hostname。
class Ce_PeForm(ModelForm):
class Meta:
model = Ce_Pe
fields = ['ce_hostname', 'pe_hostname', 'px_hostname', 'vrf', 'ce_wan_port', 'ce_local_device', 'ce_local_device_port', 'pe_wan_port', 'pe_local_device', 'pe_local_device_port', 'wan_vlan', 'outer_vlan', 'idn', 'vrf_22_co
st']
def __init__(self, *args, order_reference, **kwargs):
super().__init__(*args, **kwargs)
order_id = str(order_reference.id)
self.fields['ce_hostname'].queryset = Ce_Base.objects.filter(order_reference=order_id,)
#self.fields['ce_wan_port'].filter(data)
self.fields['ce_wan_port'].choices = [('Gi0/0','Gi0/0'), ('Gi0/1','Gi0/1')]
表单只在呈现模板时创建一次。您必须使用JavaScript来操作选择字段。您可以将所有可能的路由器及其接口呈现在html的脚本标记中,这些标记可以被js文件访问,或者您可以根据您的路由器选择进行AJAX调用,以返回适当的端口选择并使用响应中的数据填充字段。