我的问题是:有没有办法创建自定义模型表单,它将使用相关模型中的指定字段而不是相关模型的ID?
澄清一下,如果我有以下两个模型:
class ModelOne(models.Model):
id = models.AutoField(primary_key = True)
name = models.CharField(unique = True, blank = False, null = False)
class ModelTwo(models.Model):
id = models.AutoField(primary_key = True)
parent = models.ForeignKey(ModelOne, blank = False, null = False)
attribute_1 = models.CharField(blank = False, null = False)
attribute_2 = models.IntegerField(blank = False, null = False)
现在,如果我使用ModelForm在ModelTwo上创建UpdateView,那么父字段将预先填充ModelOne中的相应ID。但是我希望它显示ModelOne的name属性,然后在表单提交上将唯一名称(ModelOne)解析为相应的ModelOne实例。我想这样做的原因是,我认为从用户的角度来看,处理ModelOne的名称(更新ModelTwo实例时)而不是它的&#34; id&#34;会更直观。< / p>
关于我如何做到这一点的任何建议?
答案 0 :(得分:1)
首先,尝试在ModelOne上定义 unicode 方法。它可能不适用于解决方案,但它值得拥有 - 它将以表单选择小部件来驱动文本值...
def __unicode__(self):
'''Warning: be careful not to use related objects here,
could cause unwanted DB hits when debugging/logging
'''
return self.name
如果这还不够,那么这样的事情可能有用(它改编自我所拥有的表格,更新了附在个人资料中的用户名)......
class M2Form(forms.ModelForm):
m1_name = forms.CharField()
class Meta:
model = ModelTwo
def save(self, *args, **kw):
# Update your name field here, something like
if self.cleaned_data.get('m1_name'):
self.instance.parent = ModelOne.objects.get(name=self.cleaned_data.get('m1_name'))
return super(M2Form, self).save(*args, **kw)
这是未经测试的,您可能需要对其进行调整以验证名称是否存在,并确保原始父字段未显示在表单上。运气好的话,第一个答案涵盖了我认为你的问题。
答案 1 :(得分:0)
使用Rog的答案作为起点并深入研究Django的一些内部结构,我最终找到了一个有效的解决方案。鉴于我的Django知识水平,我想有一个更好的方法来做到这一点;所以,如果您有其他方法,请添加它。
基于以上两个模型,我创建了以下表单类:
class CustomForm(forms.ModelForm):
parent = models.CharField(label='Name')
class Meta:
model = ModelTwo
exclude = ['parent']
def __init__(self,*args,**kwargs):
# The line of code below is the one that I was looking for. It pre-populates
# the "parent" field of the form with the "name" attribute of the related
# ModelOne instance.
kwargs['initial']['parent'] = kwargs['instance'].parent.name
super(CustomForm,self).__init__(*args,**kwargs)
# The next line is for convenience and orders the form fields in our desired
# order. I got this tip from:
# http://stackoverflow.com/questions/913589/django-forms-inheritance-and-order-of-form-fields
self.fields.keyOrder = ['parent','attribute_1','attribute_2']
def save(self, *args, **kwargs):
if self.cleaned_data.get('parent'):
# This section of code is important because we need to convert back from the
# unique 'name' attribute of ModelOne to the corresponding instance so that
# ModelTwo can be saved. Thanks goes to Rog for this section of code.
self.instance.parent = ModelOne.objects.get(name=self.cleaned_data.get('parent'))
return super(CustomForm, self).save(*args, **kwargs)