我有两个型号
class Model_1(models.Model):
foreign_key_field = models.ForeignKey(Model_2)
class Model_2(models.Model):
number = models.IntegerField()
我需要一个ModelForm来编辑Model_2对象。在该表单中,我想要一个包含所有Model_1对象的列表,以及用于复选那些应该使用特定Model_2对象作为ForeignKey的Model_1字段的选项。
实际上,它应该像ManyToMany字段一样工作,但是在ManyToOne关系中。
也许ModelForm看起来像这样:
class SetForeignKeyForm(ModelForm):
is_linked = BooleanField(required=False)
class Meta:
model = ModelName
fields = ()
def clean_is_linked(self):
if self.cleaned_data['is_linked']:
self.fields['foreign_key_field'] = self.object
和视图:
class Model2UpdateView(ModelFormSetView):
model = Model_2
form_class = SetForeignKeyForm
def get_queryset(self):
return Model_2.objects.all()
我不知道如何在我的自定义ModelForm中获取Model_2对象,所以我不知道如何保存Model_1对象是否链接到特定的Model_2对象。
我最终会看到类似
的输出<h1>Model_2 object</h1>
<form method="post" action="">
<tr>
<td>Model1 object name</td>
<td><input type="checkbox" name="model1_id_1" /></td>
</td>
<tr>
<td>Model1 object name</td>
<td><input type="checkbox" name="model1_id_2" checked="checked" /></td>
</td>
<tr>
<td>Model1 object name</td>
<td><input type="checkbox" name="model1_id_3" /></td>
</tr>
<input type="submit" />
</form>
修改1
我做了一些似乎有用的东西,但我不确定它是否正确完成。
我有一个观点
class Model2Detail(ModelFormSetView):
model = Model1
template_name = 'tpl.html'
form_class = PairingForm
extra = 0
def get_queryset(self):
self.object = get_object_or_404(Model2, slug=self.kwargs['slug'])
return Model1.objects.all() # those objects with ForeignKey field
def formset_valid(self, formset):
for form in formset:
form.instance.foreign_key_field = self.object # set Model1's ForeignKey field
form.save()
return HttpResponseRedirect(self.get_success_url())
def get_success_url(self):
return self.object.get_absolute_url()
和表格
class PairingForm(ModelForm):
is_linked = BooleanField(required=False)
class Meta:
fields = ()
model = Model2 # those objects __without__ ForeignKey field
def __init__(self, *args, **kwargs):
super(PairingForm, self).__init__(*args, **kwargs)
if self.instance.foreign_key_field: # if object already paired
self.fields['is_linked'].initial = True
def save(self, commit=True, force_insert=False, force_update=False, *args, **kwargs):
obj = super(PairingForm, self).save(commit=False, *args, **kwargs)
if self.cleaned_data['is_linked']:
obj.foreign_key_field = self.instance.entry
else:
obj.foreign_key_field = None # remove pairing
obj.save()
对我而言,我尝试在视图和表单中设置ForeignKey字段似乎是错误的,但我不知道应该如何。
修改2
我的代码有效,但实际上我不知道为什么。如果我没有在formset_valid
中设置外键字段,则它不再起作用,所以我觉得有些问题。我不应该在没有覆盖formset_valid
的情况下使其工作吗?我是否在我的表单中使用Meta.model中的正确模型?
答案 0 :(得分:0)
我认为在表单中仅修改一种类型的对象是一种好习惯。这样可以保持事物的分离,而且我相信,这会使预期的行为更加清晰。
考虑到这一点,我认为您应该将此视为“编辑Model_2对象”,而不是将其视为“编辑一堆Model_1对象”,方法是在每个对象上设置或取消设置值。在该体系结构中,您可以使用表单集,每个表单都有一个复选框字段(例如,is_linked
)。在formset的save_new
或save_existing
方法中,您可以检查该字段并相应地在要保存的特定对象上设置外键。
您的更新版本看起来非常不错。我看到的唯一问题是你的formset_valid
方法似乎为表单中的每个对象设置了外键字段,但你真的只想在is_linked
为True时设置它,对吧?在我看来ParingForm
实际上在保存时做了正确的事情,因此您不需要在formset_valid
中设置值。