Django dependant filters using json list variable contained within foreign key
У меня есть форма, которую может заполнить пользователь. Мне нужно зависимое выпадающее меню, чтобы при выборе маршрутизатора (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, но мне нет смысла делать это, так как она может меняться каждый раз, когда пользователь меняет выпадающее меню, а не только при инициализации класса или в посте.
Вот мой 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>
Форма создается только один раз во время рендеринга шаблона. Для манипуляций с полем выбора вам придется использовать JavaScript. Либо вы отображаете все возможные маршрутизаторы и их интерфейсы в теге script вашего html, который может быть доступен через js-файл, либо вы размещаете вызов AJAX, основанный на выборе маршрутизатора, чтобы вернуть соответствующие варианты портов и заполнить поле данными из ответа.