当前位置: 代码迷 >> python >> 澄清Django Choices Mechanics
  详细解决方案

澄清Django Choices Mechanics

热度:31   发布时间:2023-06-13 16:59:29.0

假设我要在建筑物中进行预订,选择根据所选择的楼层而变化。

在我的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个参数是什么意思?

这比Django问题更像是Python问题,因为它比其他任何事情都更关注对象继承和初始化。

这是简短的版本:

__init__是初始化实例时调用的方法。 它实际上不是构造函数(称为__new__ ),但是当您执行类似的操作时

booking_form = BookingForm(room_choices) 

__init__将在构造函数之后调用。

通过调用super(BookingForm, self).__init__(*args, **kwargs)您可以允许初始化使继承链冒泡。 在这种情况下,您允许forms.Form进行所需的所有初始化,包括定义表单和设置您定义的字段。

Form实例上定义字段之后,您将覆盖room字段上的选择。 如果您想尝试切换这两个线,从而使覆盖发生父初始化之前,你会得到一个KeyErrorself.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将继承链中的任何其他潜在参数。