Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override Django form field's name attr

I've built a Django form that submits to a page on another domain (that I don't control). The idea is that I have a nicely styled, neatly generated form that fits neatly into my own site and takes the user elsewhere when it is submitted.

However,

  • If that other form changes the names of any of its fields, I need to change the names of the fields in my form and then change those names everywhere else in my application - since the name attr is coupled to the name of the property used for the field.
  • If the remote form uses silly names then my form object must also have properties with silly names which pollutes my application's code.
  • Should those names happen to be reserved words in Python (e.g. from), then it is difficult or impossible to create a Django form object representation.

Is there a way to specify a different string to use for the 'name' attribute when the field is displayed? Thus, decoupling the HTML form from the class that represents it.

This would need two components:

  1. Override the name value in the widget
  2. Make the form read this value from request.POST when it is bound

I only need step 1 in this case, but step 2 is relevant to solve the problems I listed above more generally

like image 563
adamnfish Avatar asked Jan 10 '12 10:01

adamnfish


2 Answers

This is a pretty horrible abuse of the API, but there is a form method called add_prefix that is called to determine what the HTML name of each field should be, taking into account the form's prefix if any. You could override that so that it looks up the field name in a dictionary somewhere and returns the name you want - not forgetting to preserve the existing prefix behaviour:

FIELD_NAME_MAPPING = {
    'field1': 'html_field1',
    'field2': 'html_field2'
}

class MyForm(forms.ModelForm):
    def add_prefix(self, field_name):
        # look up field name; return original if not found
        field_name = FIELD_NAME_MAPPING.get(field_name, field_name)
        return super(MyForm, self).add_prefix(field_name)
like image 84
Daniel Roseman Avatar answered Sep 24 '22 06:09

Daniel Roseman


I've implemented a simple function which overwrites the widget render method and assigns a custom name:

def namedWidget(input_name, widget=forms.CharField):
    if isinstance(widget, type):
        widget = widget()

    render = widget.render

    widget.render = lambda name, value, attrs=None: \
        render(input_name, value, attrs)

    return widget

The usage is simple:

class AliasCreationForm(forms.Form):
    merchant_id = forms.CharField(
        max_length=30,
        widget=namedWidget('PSPID', forms.HiddenInput),
    )
like image 34
GaretJax Avatar answered Sep 23 '22 06:09

GaretJax