我整天都在努力解决这个问题,希望有人能提供帮助。 我在同一张表中按类别对所有层次结构进行了分类。 在表单创建过程中,我想按类别将每个层次结构分开,并使用ModelMutipleChoiceField呈现它,因为并非所有层次结构都一起显示。
问题是在提交表单时出现的,因为我需要遍历每个ModelMutipleChoiceField字段并获取选定的值,然后将它们复制到模型字段中,然后再保存表单。但是,我无法遍历ModelMutipleChoiceField并获取选定的值。我也不知道如何在ModelField上设置这些值
注意:层次结构的数量可以变化。
这是我的代码:
我正在使用Django MPTT,并使用2个模型创建层次结构。 一个是类别(层次结构),另一个是层次结构的节点(HierarchyNode_MPTT)。
然后,我创建了一个单独的模型,该模型的ManyToManyField指向HierarchyNode_MPTT。
Models.py
class Hierarchy(models.Model):
ID = kp.ObjectIDField()
name = kp.ObjectNameField()
ext_hierarchy = kp.ObjectTechnicalID()
seq_no = kp.SeqNoField(unique=True)
mptt_seq_no = models.PositiveIntegerField()
class HierarchyNode_MPTT(MPTTModel):
id = kp.ObjectIDField()
name = kp.ObjectNameField()
description = kp.ObjectDescriptionField()
ext_node_id = kp.ObjectShortNameField()
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
hierarchy = models.ForeignKey(Hierarchy, on_delete=models.CASCADE, null=True, blank=True, related_name='children')
class Configuration(models.Model):
uuid = kp.ObjectIDField()
name = kp.ObjectNameField()
description = kp.ObjectDescriptionField()
hierarchy_nodes = models.ManyToManyField(HierarchyNode_MPTT)
然后,我创建了表单并实现了 init 方法,以根据需要自动创建尽可能多的层次结构。
form.py
class ConfigurationCreateForm(forms.ModelForm):
class Meta:
model = ForecastConfiguration
exclude = ['uuid', 'hierarchy_nodes']
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
hierarchies = Hierarchy.objects.all()
for hierarchy in hierarchies:
field_name = 'hierarchy_%s' % (hierarchy.mptt_seq_no,)
self.fields[field_name] = TreeNodeMultipleChoiceField(queryset=HierarchyNode_MPTT.objects.all().filter(hierarchy=hierarchy),label=hierarchy.name, required=True)
try:
self.initial[field_name] = HierarchyNode_MPTT.objects.root_node(tree_id=hierarchy.mptt_seq_no)
except IndexError:
self.initial[field_name] = ''
def copy_hierarchies(self, *args, **kwargs):
hierarchies = Hierarchy.objects.all()
choice_list = list()
for hierarchy in hierarchies:
field_name = 'hierarchy_%s' % (hierarchy.mptt_seq_no,)
selected_values = self.cleaned_data.get(field_name)
for selection in selected_values:
choice_list.append(selection)
self.initial['hierarchy_nodes'] = choice_list
最后,想法是在View上实现post方法以遍历创建的层次结构,然后将该值分配给名为“ hierarchy_nodes”的模型字段
view.py
class ConfigurationCreateView(CreateView):
model = Configuration
form_class = ConfigurationCreateForm
template_name = 'frontend/base/config_create.html'
def get(self, request, *args, **kwargs):
form = ConfigurationCreateForm(user=request.user)
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
form.copy_hierarchies(*args, **kwargs)
if form.is_valid():
fcc_form = form.save(commit=True)
messages.add_message(self.request, messages.INFO, 'Your Forecast Configurations has been saved')
return redirect(reverse('planning_detail', kwargs={'uuid': self.fcc_form.uuid}))
else:
messages.add_message(self.request, messages.ERROR, 'Error when creating the Forecast Configuration')
return render(request, self.template_name, {'form': form})
如您所见,我在表单中创建了一个名为copy_hierarchies的方法,这是我计划复制层次结构值的位置,这是我遇到问题的方法。
如果有使用Javascript执行此操作的简便方法,我欢迎这些选项。
先谢谢了。
答案 0 :(得分:0)
我无法使用多选字段解决此问题,但是,以下是ChoiceField(单选)的解决方案
1)更改了view.py post方法以保存对象。 2)保存模型后,我遍历请求输入字段,并将值附加到创建的实例中。 3)保存实例。 4)删除form.py
中的copy_hierarchies方法这是在 views.py
中创建的代码段def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
fcc = form.save()
for key in self.request.POST:
# check only the ones w/ 'hierarchy_#'
if key.startswith('hierarchy_'):
# get form field object
id = self.request.POST[key]
node = HierarchyNode_MPTT.objects.get(id=id)
# add to object instance
fcc.hierarchy_nodes.add(node)
fcc.save()