假设我想在建筑物中预订,并且选择根据所选择的楼层而变化。
在 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个参数是什么意思?
答案 0 :(得分:1)
这更像是一个Python问题,而不是Django问题,因为它更多地关注对象继承和初始化。
以下是简短版本:
__init__
是在初始化实例时调用的方法。它实际上不是一个构造函数(称为__new__
),但当你执行类似
booking_form = BookingForm(room_choices)
__init__
将在构造函数之后调用。
通过调用super(BookingForm, self).__init__(*args, **kwargs)
,您可以允许初始化来冒充继承链。在这种情况下,您允许forms.Form
执行它需要执行的所有初始化,包括定义表单和设置您定义的字段。
在Form
实例上定义字段后,您将覆盖room
字段上的选项。如果您尝试切换这两行,以便在父初始化之前进行覆盖,则会得到KeyError
,因为self.fields
此时不存在。
至于params:
self
是对当前实例的引用,必须将其传递给每个实例方法。这就是Python处理实例方法的方式(它相当于Java中的this
)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
特别有用 - 就像你的情况一样,{{1}有一大堆参数 - 你不接触。您只需在它们前面添加参数,forms.Form.__init__
和*args
将任何其他潜在参数放在继承链上。