澄清Django选择力学

时间:2015-10-22 04:52:41

标签: python django oop

假设我想在建筑物中预订,并且选择根据所选择的楼层而变化。

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 个答案:

答案 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将任何其他潜在参数放在继承链上。