【发布时间】:2017-12-17 00:17:17
【问题描述】:
如果我们有一个modelForm,其中一些字段不直接对应于模型,我们如何让表单以自定义方式处理它们,同时默认保存其余字段?
例如,我们有一个支持多语言描述的项目模型。这些模型是:
class Item(models.Model):
name = models.ForeignKey(Localization)
on_sale = models.BooleanField(default=False)
class Localization(models.Model):
de = models.TextField(blank=True, null=True, verbose_name='de')
eng = models.TextField(blank=True, null=True, verbose_name='eng')
添加/编辑项目的表单如下所示:
class ItemForm(forms.ModelForm):
id = forms.CharField(widget=forms.HiddenInput(), max_length=128, label='')
name_eng = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:200px;'}), label='eng')
name_de = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:200px;'}), label='de')
on_sale = forms.CharField(widget=forms.CheckboxInput(), label='on_sale', )
class Meta:
model = Item
fields = ('id', 'on_sale',)
现在保存这个表单应该做的是为一个新的项目 - 创建具有两个名称字段的本地化对象,然后创建一个具有 on_sale 字段的项目对象,链接到本地化对象。对于现有项目 - 编辑相应的本地化对象,然后编辑项目本身的 on_sale 字段。
我使用一个单独的函数完成了这项任务,该函数分别处理来自请求的自定义字段,但是通过表单的 save() 方法完成这一切看起来更好。还是我错了?
PS 很抱歉提出一个明显陈词滥调的问题,但我只是没能用其他例子做我想做的事。
更新:
在此处的提示的帮助下,我实际上让它按照我想要的方式工作。代码是这样的,请告诉我是否可以优化。
class NameForm(forms.ModelForm):
# id = forms.CharField(widget=forms.HiddenInput(), max_length=128, label='')
id = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:200px;'}), label='id', required=False)
name_eng = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:200px;'}), label='eng')
name_de = forms.CharField(widget=forms.TextInput(attrs={'style': 'width:200px;'}), label='de')
gender = forms.CharField(widget=forms.CheckboxInput(), label='gender', required=False)
class Meta:
model = Name
fields = ('id', 'gender',)
def save(self):
instance = super(NameForm, self).save(commit=False)
obj_id = self.cleaned_data['id']
if obj_id:
instance_bd = Name.objects.get(pk=obj_id)
loc = instance_bd.name
loc.de = self.cleaned_data['name_de']
loc.eng = self.cleaned_data['name_eng']
loc.save()
instance.id = obj_id
else:
loc = Localization(de=self.cleaned_data['name_de'], eng=self.cleaned_data['name_eng'])
loc.save()
instance.name = loc
instance.save()
return instance
视图很简单
@login_required
def admin_lists(request):
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
form.save()
forms = {'name': NameForm()}
return render(request, 'admin/lists.html', {'forms': forms})
【问题讨论】:
-
您在views.py 的表单验证中寻找的是
commit=false。看看这里stackoverflow.com/questions/12848605/…。发表你的意见。py 也许我可以告诉你我的意思。 -
@hansTheFranz 谢谢。我实际上让它按照我想要的方式工作,上面的代码。如果有任何可能的改进,请告诉我。