djangodjango-formsopenstackopenstack-horizon

how to override handle method in SelfHandlingForm in OpenStack horizon?


I want to add some more data to properties of CreateImageForm in handle method. So when it create image, it has one custom property abc.

After changes code might be like this

def handle(self, request, data):
        # Glance does not really do anything with container_format at the
        # moment. It requires it is set to the same disk_format for the three
        # Amazon image types, otherwise it just treats them as 'bare.' As such
        # we will just set that to be that here instead of bothering the user
        # with asking them for information we can already determine.
        if data['disk_format'] in ('ami', 'aki', 'ari',):
            container_format = data['disk_format']
        else:
            container_format = 'bare'

        meta = {'is_public': data['is_public'],
                'protected': data['protected'],
                'disk_format': data['disk_format'],
                'container_format': container_format,
                'min_disk': (data['minimum_disk'] or 0),
                'min_ram': (data['minimum_ram'] or 0),
                'name': data['name'],
                'properties': {}}

        if data['description']:
            meta['properties']['description'] = data['description']
        if data['architecture']:
            meta['properties']['architecture'] = data['architecture']

        ###################################
        # My changes 
        ###################################
        meta['properties']['abc'] = 'def'

        if (settings.HORIZON_IMAGES_ALLOW_UPLOAD and
                policy.check((("image", "upload_image"),), request) and
                data.get('image_file', None)):
            meta['data'] = self.files['image_file']
        else:
            meta['copy_from'] = data['copy_from']

        try:
            image = api.glance.image_create(request, **meta)
            messages.success(request,
                _('Your image %s has been queued for creation.') %
                data['name'])
            return image
        except Exception:
            exceptions.handle(request, _('Unable to create new image.')) 

I want to do this without changing existing code, like overriding or inheriting class.


Solution

  • No override way without touching any code.

    from ModalFormView in horizon/forms/views.py
    You can see that form_valid method uses form.handle(...).

    So this handle method is HARD CODED in Horizon.

    At least, you have to touch one place to override handle without directly modifying CreateImageForm:

    # openstack_dashboard/dashboards/project/images/images/forms.py
    class YourCreateImageForm(CreateImageForm): # <== Create your form inherited from CreateImageForm!
        def handle(self, request, data):
            ...
            (the whole your logic here)
            ...
    
    # openstack_dashboard/dashboards/project/images/images/views.py
    class CreateView(forms.ModalFormView):
        form_class = project_forms.YourCreateImageForm  # <== touch here!
        ...
    

    Maybe you want to override it because you are afraid of the conflict when upgrading Horizon in future.

    If you want to customize Horizon and don't touch any thing, the best way is:

    1. Create a your dashborad(tab)
    2. Add your panel. In your panel, you can easily inherit any classes you want from Project/Admin, and change the part you want to. Add logic, add form elements, add anything...

    Finally, in your case, you just want to add ONE line into code, so why not just add it? If you upgrade your Horizon, I don't think that this part will cause a conflict.