[openstack-dev] [Horizon] Second MultipleChoiceList is not showing values...

Paul Michali pcm at cisco.com
Mon Jun 17 20:56:28 UTC 2013


Need some guidance here…

Under Launch Instance, Networking tab, we have a custom Horizon version that also has a "Policy Profile" Checkbox field, in addition to the Network" MultipleChoiceList field.

Now, we'd like to be able to select a policy for each network selected.  The initial thought was to convert the Policy Profile Checkbox field into a MultipleChoiceList (If there is a better way to define these, please let us know!).  With the Network field, as the user drags and drops networks, they are associated with nic1, nic2, nic3… I was figuring the same thing could be done with the "Policy Profile". So…

I changed the field type and added a widget, the same as with the Network field. Then, I modified the populate function (and the contribute function, but I'm not quite sure yet how that plays into this). The code snippet looks like this:

class SetNetworkAction(workflows.Action):
    network = forms.MultipleChoiceField(label=_("Networks"),
                                        required=True,
                                        widget=forms.CheckboxSelectMultiple(),
                                        error_messages={
                                            'required': _(
                                                "At least one network must"
                                                " be specified.")},
                                        help_text=_("Launch instance with"
                                                    "these networks"))
    profile = forms.MultipleChoiceField(label=_("Policy Profiles"),
                                        required=False,
                                        widget=forms.CheckboxSelectMultiple(),
                                        help_text=_("Launch instance with "
                                                     "these policy profile(s)"))


    class Meta:
        name = _("Networking")
        permissions = ('openstack.services.network',)
        help_text = _("Select networks for your instance.")

    def populate_network_choices(self, request, context):
        try:
            tenant_id = self.request.user.tenant_id
            networks = api.quantum.network_list_for_tenant(request, tenant_id)
            for n in networks:
                n.set_id_as_name_if_empty()
            network_list = [(network.id, network.name) for network in networks]
            LOG.error("PCM Populating NETWORKS: %s" % network_list)
        except:
            network_list = []
            exceptions.handle(request,
                              _('Unable to retrieve networks.'))
        return network_list

    def populate_profile_choices(self, request, context):
        try:
            profiles = api.quantum.profile_list(request, 'policy')
            for p in profiles:
                p.set_id_as_name_if_empty()
            profile_list = [(p.id, p.name) for p in profiles]
            LOG.error("PCM Populating PROFILES: %s" % profile_list)
        except:
            profile_list = []
            exceptions.handle(request, _("Unable to retrieve profiles."))
        return profile_list


class SetNetwork(workflows.Step):
    action_class = SetNetworkAction
    template_name = "project/instances/_update_networks.html"
    contributes = ("network_id", "profile_id")

    def contribute(self, data, context):
        if data:
            networks = self.workflow.request.POST.getlist("network")
            # If no networks are explicitly specified, network list
            # contains an empty string, so remove it.
            networks = [n for n in networks if n != '']
            if networks:
                context['network_id'] = networks

            profiles = self.workflow.request.POST.getlist("profile")
            # If no profiles are explicitly specified, profile list
            # contains an empty string, so remove it.
            profiles = [p for p in profiles if p != '']
            if profiles:
                context['profile_id'] = profiles
            LOG.debug("PCM at contribute %d - %d" %(len(networks), len(profiles)))
        return context
        ...

I do see the populate functions called and there is data there. In the HTML template, I modified the row for the Policy Profile from using a "{{form.profile }}" to having the same code as the Network list field has. I created identical CSS definitions for the profile styles. Code looks like this:

<table class="table-fixed" id="networkListSortContainer">
  <tbody>
    <tr>
      <td class="actions">
        <h4 id="selected_network_h4">{% trans "Selected Networks" %}</h4>
        <ul id="selected_network" class="networklist">
        </ul>
        <h4>{% trans "Available networks" %}</h4>
        <ul id="available_network" class="networklist">
        </ul>
      </td>
      <td class="help_text">
          {% include "project/instances/_launch_network_help.html" %}
      </td>
    </tr>
    
    <tr>
      <td class="actions">
        <h4 id="selected_profile_h4">{% trans "Selected Profiles" %}</h4>
        <ul id="selected_profile" class="profilelist">
        </ul>
        <h4>{% trans "Available profiles" %}</h4>
        <ul id="available_profile" class="profilelist">
        </ul>
      </td>
      <td class="help_text">
          {% include "project/instances/_launch_profile_help.html" %}
      </td>
    </tr>
  </tbody>
</table>


When I try this, I see the choices for the "Available Networks" and I can drag and drop them to the "Selected Networks", but the "Available Profiles" list is empty. No box or anything shown, just the h4 headings. I did try having a second table, with id profileListSortedContainer, but the same results occurred.

BTW, if I rename the populate_network_choices to populate_policy_choices, and vice versa, I see the list of policies in the "Available Networks" and nothing still in the "Available Policies" field.

What am I missing/doing wrong, such that the policy choices information is not being filled out in the template?

How does the populate_policy_choices info get used in the template. I'm missing that part of things?

At a higher level, is there a better way to relate these two fields?  I still need to verify that for each network there needs to be one policy, and whether or not the policy choice needs to be unique (as in not having the same policy for multiple networks - which MAY be allowed - I need to check).

Thanks in advance!



PCM (Paul Michali)

MAIL pcm at cisco.com
IRC   pcm_  (irc.freenode.net)
TW   @pmichali

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openstack.org/pipermail/openstack-dev/attachments/20130617/a34a4653/attachment.html>


More information about the OpenStack-dev mailing list