Django-mptt: Как автоматически выбирать детей в админке при выборе родителя?
У меня возникли проблемы при выборе родителя - дети не выбираются автоматически. Например, когда я выбираю Cluster #2
, его дочерние элементы (Store #1
и Store #2
) не выбираются:
Как я могу это исправить?
Это важно, потому что мне нужно создавать связи "многие-ко-многим" (Deviation-Orgunit) только с помощью stores
(с листьями).
Модели:
from django.db import models
from mptt.fields import TreeForeignKey
from mptt.models import MPTTModel
class Orgunit(MPTTModel):
name = models.CharField(
max_length=100
)
type = models.CharField(
choices=[
('MACRO', 'Макро'),
('CLUSTER', 'Кластер'),
('KUST', 'Куст'),
('STORE', 'Магазин')
],
max_length=100
)
parent = TreeForeignKey(
'self',
on_delete=models.CASCADE,
null=True,
blank=True,
related_name='children'
)
def __str__(self):
return self.name
class Deviation(models.Model):
name = models.CharField(max_length=100)
number = models.PositiveIntegerField(null=True)
orgunits = models.ManyToManyField('orgunits.Orgunit')
def __str__(self):
return self.name
Admin:
from django.contrib import admin
from deviations.forms import MyForm
from deviations.models import Deviation
@admin.register(Deviation)
class DeviationAdmin(admin.ModelAdmin):
form = MyForm
Форма:
from django.forms import ModelForm, widgets
from mptt.forms import TreeNodeMultipleChoiceField
from orgunits.models import Orgunit
class MyForm(ModelForm):
orgunits = TreeNodeMultipleChoiceField(queryset=Orgunit.objects.all(), widget=widgets.SelectMultiple())
class Meta:
model = Orgunit
fields = '__all__'
В качестве примера привожу следующий код :
private void CheckAllChildNodes(TreeNode treeNode, bool nodeChecked)
{
foreach (TreeNode node in treeNode.Nodes)
{
node.Checked = nodeChecked;
if (node.Nodes.Count > 0)
{
this.CheckAllChildNodes(node, nodeChecked);
}
}
}
private void treeView_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Action != TreeViewAction.Unknown)
{
if (e.Node.Nodes.Count > 0)
{
if (!e.Node.Checked)
{
this.CheckAllChildNodes(e.Node, e.Node.Checked);
}
}
}
if (e.Node.Parent != null)
{
TreeNode n = e.Node;
while (n.Parent != null)
{
if (n.Checked)
{
n.Parent.Checked = true;
}
n = n.Parent;
}
}
}
В противном случае, есть дополнительная документация по событию AfterCheck, которое делает это