使用MPTT

时间:2018-10-02 22:28:56

标签: django django-mptt

我整天都在努力解决这个问题,希望有人能提供帮助。 我在同一张表中按类别对所有层次结构进行了分类。 在表单创建过程中,我想按类别将每个层次结构分开,并使用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执行此操作的简便方法,我欢迎这些选项。

先谢谢了。

1 个答案:

答案 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()