我需要创建一个层次结构,并添加了模型列表,如下所示:
class Category(models.Model):
name = models.CharField(max_length=255)
class Form(models.Model):
parent = models.ForeignKey('Category', related_name='category', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
class Type(models.Model):
parent = models.ForeignKey('Form', related_name='form', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
class Point(models.Model):
parent = models.ForeignKey('Point', related_name='point', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
因此,请提出如何处理此结构的建议。我必须执行2种情况:
那么,实现它的最佳方法是什么?
答案 0 :(得分:1)
说实话,每个模型中都有相似的字段(name
和parent
)。而不是像这样设计,为什么不使用相同的模型,例如:
class Node(models.Model):
CATEGORY = 'C'
FORM = 'F'
TYPE = 'T'
POINT = 'P'
CHOICES = (
(CATEGORY, 'CATEGORY'),
(FORM, 'FORM'),
(TYPE, 'TYPE'),
(POINT, 'POINT'),
)
node_type = models.CharField(
max_length=2,
choices=CHOICES,
default=CATEGORY
parent = models.ForeignKey('self', null=True, default=None, related_name='children')
name = models.CharField(max_length=255, null=True, default=None)
现在,如果您想从点到点进行输入,那么您可以这样做:
def get_children(node):
qset = Node.objects.filter(pk=node.pk)
for child in node.children.all():
qset.union(get_children(child)) # using recursion
return qset
def get_parents(node):
qset = Node.objects.filter(pk=node.pk)
while(node.parent):
qset.union(Node.objects.filter(pk=node.parent.pk))
node = node.parent
return qset
让我们说您有一些额外的数据可能与某个点的模型有关,您可以与该节点建立OneToOne关系,而另一个模型将包含该额外数据。例如:
class ExtraPoint(models.Model):
point = models.OneToOneField(Node, related_name='point')
data = models.CharField(max_length=255)
然后您可以像这样访问该数据:
for node in Node.objects.all():
if node.point:
print(node.point.data)