我有一些表单字段,我想根据是否满足某个条件来包含/排除.我知道如何包含和排除表单元素,但是当我希望它根据函数的结果显示元素时,我很难做到.
这是我的表格:
class ProfileForm(ModelForm): # this_team = get Team instance from team.id passed in # how? def draft_unlocked(self): teams = Team.objects.order_by('total_points') count = 0 for team in teams: if team.pk == this_team.pk: break count += 1 now = datetime.datetime.now().weekday() if now >= count: # show driver_one,driver_two,driver_three else: # do not show driver_one,driver_three class Meta: model = Team
我想要完成的是,根据总积分的排名,团队不应该在指定的日期之前改变他们的驾驶员.在比赛中,排名最后一支球队可以在周一添加/减少一名车手,倒数第二支球队可以在周二增加/减少,依此类推……
所以第一个问题 – 如何从传入的id中获取表单内部的Team实例.而且,如何根据draft_unlocked()的结果包含/排除.
或者也许有更好的方法来做所有这些?
非常感谢大家.
解决方法
这实际上相当简单(条件字段设置) – 这是一个简单的例子:
from django.forms import Modelform from django.forms.widgets import HiddenInput class SomeForm(ModelForm): def __init__(self,*args,**kwargs): # call constructor to set up the fields. If you don't do this # first you can't modify fields. super(SomeForm,self).__init__(*args,**kwargs) try: # make somefunc return something True # if you can change the driver. # might make sense in a model? canchangedriver = self.instance.somefunc() except AttributeError: # unbound form,what do you want to do here? canchangedriver = True # for example? # if the driver can't be changed,use a input=hidden # input field. if not canchangedriver: self.fields["Drivers"].widget = HiddenInput() class Meta: model = SomeModel
那么,关键点是:
> self.instance表示绑定对象,如果表单已绑定.我相信它是作为命名参数传递的,因此在kwargs中,父构造函数用它来创建self.instance.
>您可以在调用父构造函数后修改字段属性.
>小部件是表单的显示方式. HiddenInput基本上意味着< input type =“hidden”... />.
有一个限制;如果修改提交的POST / GET数据,我可以篡改输入以更改值.如果您不希望发生这种情况,需要考虑的事项是覆盖表单的验证(clean())方法.请记住,Django中的所有内容都只是对象,这意味着您可以实际修改类对象并随机添加数据(虽然它不会被保留).所以在__init__中你可以:
self.instance.olddrivers = instance.drivers.all()
然后在你的表格的干净方法:
def clean(self): # validate parent. Do this first because this method # will transform field values into model field values. # i.e. instance will reflect the form changes. super(SomeForm,self).clean() # can we modify drivers? canchangedriver = self.instance.somefunc() # either we can change the driver,or if not,we require # that the two lists are,when sorted,equal (to allow for # potential non equal ordering of identical elements). # Wrapped code here for niceness if (canchangedriver or (sorted(self.instance.drivers.all()) == sorted(self.instance.olddrivers))): return True else: raise ValidationError() # customise this to your liking.