使用Django模型表单时,我经常这样做:
def my_view(request):
new_entry = MyModel(name='a')
form = MyModelForm(instance=new_entry)
...
我想用modelformset做类似的事情。这样的事情是理想的:
def my_view(request):
MyFormSet = modelformset_factory(MyModel, form=MyModelForm)
new_entries = [MyModel(name='a'), MyModel(name='b')]
formset = MyFormSet(instances=new_entries) # off course this does not work
...
由于项目尚未存储在数据库中,因此我无法使用查询集设置实例。如果我想使用初始,我必须声明表单中的字段,这是不理想的,似乎有点hacky。
有关如何在modelformset中设置每个模型的实例的任何建议吗?
答案 0 :(得分:4)
好的,我认为我找到了解决方案。
class FormSetWithInstances(BaseFormSet):
def __init__(self, *args, **kwargs):
self.instances = kwargs.pop('instances')
super(FormSetWithInstances, self).__init__(*args, **kwargs)
def get_form_kwargs(self, index):
form_kwargs = super(FormSetWithInstances, self).get_form_kwargs(index)
if index < len(self.instances):
form_kwargs['instance'] = self.instances[index]
return form_kwargs
使用此modelformsets或inlinemodelformsets时要小心,因为查询集将覆盖您设置的实例。
答案 1 :(得分:2)
另一种方法:
class FormSetWithInstances(BaseFormSet):
def get_form_kwargs(self, index):
kwargs = super(FormSetWithInstances, self).get_form_kwargs(index)
instances = kwargs.pop('instances')
try:
kwargs.update({'instance': instances[index])
except IndexError:
pass
return kwargs
然后,在创建FormSetWithInstances
的实例时,您将实例列表作为表单kwarg传递:
form_set = FormSetWithInstances(form_kwargs={'instances': [...]})
我个人更喜欢这种方法,因为它利用了现有的类基础结构,而不是在被覆盖的__init__()
中定义自定义类成员。此外,它位于docs。
答案 2 :(得分:1)
我不知道在您尝试传递实例列表时有一种简单的方法。根据您的使用情况,这里有两个选项可供使用。
您可以provide initial data获取模型表单集。这应该是字典列表,而不是模型实例:
initial = [{'name': 'a'}, {'name': 'b'}]
formset = MyFormSet(
queryset=MyModel.objects.none(),
initial=initial,
)
请注意,我已将查询集设置为空查询集。如果您没有这样做,那么formset将显示现有实例,初始数据将用于新实例。
如果您希望在表单中包含不希望包含的字段的初始值,则可以在[保存表单集]时设置这些值。
instances = formset.save(commit=False)
names = ['a', 'b']
for instance, name in zip(instances, names):
instance.name = name
instance.save()