I think you're mixing up classes and functions here.
This:
class UploadFileForm(forms.Form):
… is not a function definition, it's a class definition. It declares that the (only) superclass of UploadFileForm
is forms.Form
.
When you do this:
form = UploadFileForm(request.POST, request.FILES)
The effect is similar to this pseudocode:
form = make new UploadFileForm
form.__init__(request.POST, request.FILES)
If you defined an __init__
method, you'd get form
, request.POST
, and request.FILES
as your arguments.
Since you didn't define an __init__
method, you inherited the one from your parent class, so it gets those three arguments.
This is almost exactly like the following Java pseudocode:
class UploadFileForm extends forms.Form {
static forms.CharField title = forms.CharField(50);
static forms.FileField file = forms.FileField();
};
UploadFileForm form = new UploadFileForm(request.POST, request.FILES);
Just as in Python, it works because you inherit constructors from the base class. Somewhere in Form
, there's a declaration like this:
public Form(int verb, int obj) {
// blah blah
}
And, in Python, the same thing is true:
def __init__(self, verb, obj):
# blah blah
In other words, Python is almost exactly as explicit as Java (in fact, slightly more so, because the self
parameter is explicit).
Also, note that your Python class attributes are equivalent to static members in Java. If you want normal instance members, you generally override __init__
and set them as self.title
, etc. there. (You don't have to do it that way—Python lets you add new members to your objects whenever you want. But it's the obvious place to do it.) For Django, this is actually pretty common—you create class attributes that the Django framework superclass uses to fill in initial instance attributes on your behalf.
Finally, the reference documentation for Django's forms.Form class doesn't actually show you the parameters, because there are (at least) four common different ways to construct Form
subclasses, all of which are described separately:
MyForm() # creates an unbound form
MyForm(data) # creates a bound form
MyForm(data, files) # creates a bound file or image form
MyForm(initial=initial_data) # creates an unbound form with initial data
And some of these accept additional optional keyword arguments.
The actual source code here shows the real prototype:
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=':',
empty_permitted=False):
Of course not all combinations of keywords make sense.
Anyway, you can see why they didn't try to explain Form
in the simple way they do other types.