动态设置django的model field的默认值操作步骤
问题背景
django的modelfield需要动态设置默认值,具体案例如下:
原始代码如下,model是Application,其中字段ignore_fort的默认值设置为False
classApplication(TimestampedModel): name=models.CharField(max_length=255,null=True) ignore_fort=models.BooleanField(default=False)
然而现在有这样一个需求:default需要根据某个变量ENV进行动态设置,如果ENV是UAT或者FAT(不区分大小写,具体分支,比如uaT01也可以),则default设置为True,否则设置为False
首先想到的是如下代码:
classApplication(TimestampedModel): name=models.CharField(max_length=255,null=True) ignore_fort=models.BooleanField(default='UAT'inENV.upper()or'FAT'inENV.upper())
通过pythonmanage.pyshell_plus启动shell调试,发现如果ENV本来设置的是什么值,逻辑正确,如果在shell中修改ENV的值,则新建的model的ignore_fort值并不是根据当前ENV值进行设置,而是保持原来的值,达不到需求。例如,ENV值本来设置为uat,那么新建app=Application(),printapp.ignore_fort结果是True,修改ENVENV='hhh',app1=Application();printapp1.ignore_fort结果还是True,而我们需要的是False。
分析
官方描述如下:
Thedefaultvalueforthefield.Thiscanbeavalueoracallableobject.Ifcallableitwillbecalledeverytimeanewobjectiscreated.
如果想要在创建对象时动态修改default的值,需要用callableobject,可以理解为函数调用?
上述代码的default值并不是callableobject,所以并不是在object创建时同台更新。
解决方法
参考正解如下,用一个函数调用实现callableobject,进而实现动态跟新default
defget_default_ignore_fort(): cur_env=ENV.upper() returnany(iincur_envforiin('UAT','FAT')) classApplication(TimestampedModel): name=models.CharField(max_length=255,null=True) ignore_fort=models.BooleanField(default=get_default_ignore_fort)
补充知识:DjangoModelChoiceField:过滤查询集并将默认值设置为对象
我有一个DjangoForm类定义喜欢这个在Models:
classAccountDetailsForm(forms.Form): ... adminuser=forms.ModelChoiceField(queryset=User.objects.all())
这工作正常,但它有一些限制,我似乎不能解决:
(1)我想在查询集上使用一个过滤器,基于传递给表单的变量accountid,如下所示:
User.objects.filter(account=accountid)
这不能在模型中工作,因为accountid不能作为一个变量传递,当然。
因此,查询集必须以某种方式在视图中定义,但就我可以看到它是一个必需的字段在Form类。
(2)我想默认选择AccountDetailsForm数据库中的一个对象,我可以在视图中选择这样:
User.objects.filter(account=accountid).filter(primary_user=1)
我试过指定adminuser作为默认值在窗体中,(它与其他标准表单字段,如CharField工作):
adminuser=User.objects.filter(account=accountid).filter(primary_user=1) ... form=AccountDetailsForm({'adminuser':adminuser}) returnrender_to_response('accounts/edit/accountdetails.html', {'form':form,'account':account})
但没有运气。
我应该使用除ModelChoiceField之外的其他方式给我这里需要的灵活性吗?
谢谢。
覆盖init方法并接受新的关键字参数
classAccountDetailsForm(forms.Form): ... adminuser=forms.ModelChoiceField(queryset=User.objects.all()) def__init__(self,*args,**kwargs): accountid=kwargs.pop('accountid',None) super(AccountDetailsForm,self).__init__(*args,**kwargs) ifaccountid: self.fields['adminuser'].queryset=User.objects.filter(account=accountid) form=AccountDetailsForm(accountid=3)
您可以随时在视图中手动设置选择。
form=AccountDetailsForm()
form.fields['adminuser'].queryset=User.objects.filter(account=accountid)
警告:您不是通过将字典传递到您的示例中的表单来设置默认值。
你实际上创建了一个绑定表,可能触发验证和所有的爵士。
要设置默认值,usetheinitialsargument.
form=AccountDetailsForm(initial={'adminuser':'3'})
翻译自:这里
以上这篇动态设置django的modelfield的默认值操作步骤就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。