问题描述
假设我要在建筑物中进行预订,选择根据所选择的楼层而变化。
在我的forms.py中
class BookingForm(forms.Form):
name = forms.CharField()
room = forms.ChoiceField()
def __init__(self, room_choices, *args, **kwargs):
super(BookingForm, self).__init__(*args, **kwargs)
self.fields['room'].choices = room_choices
并在views.py中
def book_room(request):
choices = Choices.all().list_values('rooms').filter(floor=floor)
room_choices = []
for c in choices:
room_choices.append((c, c), )
booking_form = BookingForm(room_choices)
我的问题是,这是什么机制?
特别是, def __init__
和方法的4个参数是什么意思?
1楼
这比Django问题更像是Python问题,因为它比其他任何事情都更关注对象继承和初始化。
这是简短的版本:
__init__
是初始化实例时调用的方法。
它实际上不是构造函数(称为__new__
),但是当您执行类似的操作时
booking_form = BookingForm(room_choices)
__init__
将在构造函数之后调用。
通过调用super(BookingForm, self).__init__(*args, **kwargs)
您可以允许初始化使继承链冒泡。
在这种情况下,您允许forms.Form
进行所需的所有初始化,包括定义表单和设置您定义的字段。
在Form
实例上定义字段之后,您将覆盖room
字段上的选择。
如果您想尝试切换这两个线,从而使覆盖发生父初始化之前,你会得到一个KeyError
的self.fields
不会在这一点上存在。
至于参数:
-
self
是对当前实例的引用,必须将其传递给每个实例方法。 这是Python的使用实例方法(这相当于涉及this
在Java中) -
room_choices
是您的参数 -
*args
和**kwargs
是Python处理任意参数的方式。
例如,如果您有类似
def foo(param1):
pass
而您调用foo(1, 2, a=5)
则会得到有关参数数量的错误。
但是,如果您这样定义方法:
def foo(param1, *args, **kwargs):
pass
并且您调用了相同的foo(1, 2, a=5)
,args现在将成为列表[1]
而kwargs将成为字典{'a': 5}
并且显然不会出现任何错误。
当您不想关心您要覆盖的父方法具有的所有参数时, *args
和**kwargs
尤其有用-就像这里的情况一样,其中forms.Form.__init__
有很多参数-你别碰。
您只需在它们前面添加参数,然后*args
和**kwargs
将继承链中的任何其他潜在参数。