For work recently I've been doing some
Django-related tasks that involve talking to an external API with
POSTed forms. Django forms objects are declared by creating a class that
inherits from django.forms.Form, with the fields of the
form declared by declaring attributes of that class. Which works well
and is clean and easy to remember—unless the API you're working
with requires a field with the same name as a Python keyword, such as
return. You can't declare a field like this as an
attribute; it will trigger a syntax error.
I spent some time scratching my head over this, and came up with this as
a workaround after source-diving to find out how Form
objects actually work:
from django import forms
class ExampleForm(forms.Form):
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, errorclass=ErrorList, label_suffix=':', empty_permitted=False, return_url=None):
forms.Form.__init__(self, data, files, auto_id, prefix, initial,
errorclass, label_suffix, empty_permitted)
if return_url is not None:
self.fields['return'] = forms.CharField(widget=forms.HiddenInput, initial=return_url)
It turns out that the attribute declaration is just syntactic sugar for
creating a dictionary of key/value pairs, which is then stored in the
fields attribute. So we can monkeypatch in extra values after
the translation. Which is somewhat more awkward and ugly, but works in a pinch.
Note that I haven't extensively tested what interactions this may cause with other forms code, so use with some caution.
A somewhat nicer way to would be to use the 'type' constructor:
That way, it's guaranteed to hit the same codepaths as if you wrote the form out "longhand".