问题描述
假设我要在建筑物中进行预订,选择根据所选择的楼层而变化。
在我的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将继承链中的任何其他潜在参数。