使用单选按钮控件选择指向嵌套内联formset中项目的外键

时间:2013-05-02 14:35:11

标签: django django-forms inline-formset

我定义了以下类,基本上定义了一个Node类。每个节点可以分配多个NodeIntf。每个NodeIntf可以分配多个NodeIntfIpaddr。其中一个NodeIntfIpaddr可能被指定为Node对象上的mgmt_ipaddr属性。其中一个可能被分配给mgmt_ipaddr_v6属性。现在在我的模板中,我基本上有一个嵌套的接口表,我想使用单选按钮选择器来选择哪个ipaddrs被选为Node对象上的mgmt_ipaddr(_v6)属性,但我不太确定怎么做。我认为,当我遍历ipaddr_formset时,我必须检查ipaddr是否代表所选的mgmt_ipaddr,但我不知道该怎么做。任何帮助将不胜感激。

class Node(models.Model):
    name = models.CharField(max_length=64, primary_key=True)
    mgmt_ipaddr = models.ForeignKey('NodeIntfIpaddr', null=True, on_delete=models.SET_NULL)
    mgmt_ipaddr_v6 = models.ForeignKey('NodeIntfIpaddr', null=True, on_delete=models.SET_NULL)

class NodeIntf(models.Model):
    intf = models.CharField(max_length=32)
    node = models.ForeignKey('Node', on_delete=models.CASCADE)
    class Meta:
        unique_together = ('node', 'intf')

class NodeIntfIpaddr(models.Model):
   node_intf = models.ForeignKey('NodeIntf', on_delete=models.CASCADE)
   ipaddr = InetAddressField()
   class Meta:
       unique_together = ('node_intf', 'ipaddr')

class NodeForm(ModelForm):
    class Meta:
        model = Node

class NodeIntfForm(ModelForm):
    class Meta:
        model = NodeIntf

class NodeIntfIpAddrForm(ModelForm):
    class Meta:
        model = NodeIntfIpaddr

NodeIntfIpaddrFormSet = modelformset_factory(NodeIntfIpaddr,
    form=NodeIntfIpAddrForm, extra=0)

class BaseNodeIntfFormSet(BaseInlineFormSet):
    def add_fields(self, form, index):
        super(BaseNodeIntfFormSet, self).add_fields(form, index)
        instance = self.get_queryset()[index]
        pk_value = instance.pk
        form.ipaddr_formset = NodeIntfIpaddrFormSet(
            queryset=NodeIntfIpaddr.objects.filter(node_intf=pk_value),
            prefix='INTF_%s' % pk_value)

NodeIntfFormSet = inlineformset_factory(Node, NodeIntf,
    form=NodeIntfForm, formset=BaseNodeIntfFormSet, extra=0)

class NodeUpdateView(UpdateView):
    form_class = NodeForm
    model = Node
    def get_context_data(self, **kwargs):
        c = super(NodeUpdateView, self).get_context_data(**kwargs)
        node = self.get_object()
        c['action'] = reverse('node-update', kwargs={'pk': node.name})
        if self.request.POST:
            node_intfs = NodeIntfFormSet(self.request.POST, instance=node)
            if node_intfs.is_valid():
                addrs = node_intfs.save_all()
        else:
            node_intfs = NodeIntfFormSet(instance=node)
        c['node_intfs_formset'] = node_intfs
        return c

模板摘录:

  <table class='node_intfs'>
      <thead>
        <tr class='node_intf'>
          <th colspan='2'></th>
          <th>Name</th>
          <th></th>
        </tr>
        <tr class='node_intf_ipaddr'>
          <th>IPv4 Mgmt<br><label><input type='radio' name='mgmt_ipaddr' value=''{{ node.mgmt_ipaddr|yesno:', checked' }}>None</label></th>
          <th>IPv6 Mgmt<br><label><input type='radio' name='mgmt_ipaddr_v6' value=''{{ node.mgmt_ipaddr_v6|yesno:', checked' }}>None</label></th>
          <th colspan='2'></th>
        </tr>
      </thead>
      <tbody>
{% for node_intf_form in node_intfs_formset %}
        <tr class='node_intf'>
          <td colspan='2'></td>
          <td>{{ node_intf_form.intf }}</td>
          <td></td>
        </tr>
{% if node_intf_form.ipaddr_formset %}
{% for ipaddr_form in node_intf_form.ipaddr_formset %}
        <tr class='node_intf_ipaddr'>
          <td>TODO</td>                                  <---- These are what I can't figure out
          <td>TODO</td>                                  <---- These are what I can't figure out
          <td></td>
          <td>{{ ipaddr_form.ipaddr }}</td>
        </tr>
{% endfor %}
{% endif %}
{% endfor %}
      </tbody>
    </table>

1 个答案:

答案 0 :(得分:0)

通过在我的模板中使用以下内容,我能够做到我需要的东西:

<td class='center'><input type='radio' name='mgmt_ipaddr' value='{{ ipaddr_form.instance.id }}'{% if node.mgmt_ipaddr_id == ipaddr_form.instance.id %} checked='checked'{% endif %}</td>
<td class='center'><input type='radio' name='mgmt_ipaddr_v6' value='{{ ipaddr_form.instance.id }}'{% if node.mgmt_ipaddr_v6_id == ipaddr_form.instance.id %} checked='checked'{% endif %}</td>

将Node对象的mgmt_ipaddr(_v6)_id与绑定到各个ipaddr表单的实例的id进行比较,可以作为ipaddr_form.instance.id访问。

为了完整起见,我之前也错过了每个node_intf_forms和ipaddr_forms的management_form。