1

私はPythonに比較的慣れておらず、コンパイル時にすべてが非常に明示的であるJavaから来ているので、おそらくここで何かが欠けています。私はそのように定義されたクラスを持っています:

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()

そして、私はそれを次のように使用しています:

...
form = UploadFileForm(request.POST, request.FILES)
...

クラスに 2 つの引数を渡しているのに、実行時に何らかの例外がスローされないのはなぜですか? 試してみると問題なく動きます。Python が可変量の引数を受け入れることは知っていますが、この場合の正しい構文はありません。なぜこれがOKなのか知りたいです。

4

1 に答える 1

8

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.

于 2013-05-30T01:01:20.493 に答える