Django: Como faço para modelar uma árvore de tipos de dados heterogêneos?

votos
5

Eu preciso armazenar uma estrutura de dados árvore no meu banco de dados, para o qual eu planeja usar django-treebeard ou possivelmente Django mptt . Minha fonte de confusão é que cada nó pode ser um dos três tipos diferentes possíveis: nós raiz será sempre um tipo A entidade, folha nós de uma entidade do tipo C, e entre em nada será uma entidade do tipo B. Eu gostaria de saber a melhor maneira de modelar esta situação.

update: Eu tentei primeiro herança modelo, e eu acho que isso poderia ser o melhor caminho a percorrer. Infelizmente API pública do Django-treebeard não é realmente concebido para lidar com isso. Eu acabei ficando-lo para trabalhar com GenericForeignKey. Muito obrigado pelas respostas.

Publicado 14/11/2008 em 21:14
fonte usuário
Em outras línguas...                            


4 respostas

votos
3

Que tal usar uma relação genérica do modelo que irá segurar a estrutura de árvore para o objeto de conteúdo para o nó que representa?

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Node(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    object = generic.GenericForeignKey('content_type', 'object_id')

Isso poderia resultar em um monte de consultas ao recuperar objetos de conteúdo para a árvore completa, mas existem formas e meios de reduzir o número de consultas necessárias.

# Assuming mptt, as I'm not familiar with treebeard's API

# 1 query to retrieve the tree
tree = list(Node.tree.all())

# 4 queries to retrieve and cache all ContentType, A, B and C instances, respectively
populate_content_object_caches(tree)
Respondeu 15/11/2008 em 13:30
fonte usuário

votos
3

Seus três tipos são provavelmente mais fácil tratada como associações FK com a árvore fundamental.

A árvore pode ser homogênea - classe MyNodeé uma subclasse direta de treebeard.Node. Seu nó pode ter uma bandeira (Root, Oriente, Folha) e FK para A ou B ou C. Isto permite alguma flexibilidade SQL-como na consulta exemplo MyNode.

Isso permite que sua árvore a crescer. Um nó pode começar como um tipo C (folha) e, em seguida, se transformar a um tipo B (intermediário). Você alterar o status, e mudar o FK.

A alternativa é um pouco mais complexo.

class MyA( treebeard.Node ):
    pass

class MyB( treebeard.Node ):
    pass

class MyC( treebeard.Node ):
    pass

Neste caso, você não pode "transformar" um nó. Quando um nó começa como um MyC, e recebe as crianças, você tem que remover o original MyCinstância, e substituí-lo com uma MyBversão que tem um novo nó como um filho. Isso não é impossível, mas pode ser doloroso.

Respondeu 15/11/2008 em 02:51
fonte usuário

votos
1

Bem, muito já é feito para você, de certa forma, porque raízes, folhas e outros já estão inerentemente identificado pela API árvore. Você pode chamar is_root () e is_leaf () em nós individuais para distingui-los.

Folhas e em intermediários podem ser do mesmo tipo de entidade e realizar o mesmo tipo de dados, com a forma como os dados são interpretados e utilizados pela aplicação dependendo do teste is_leaf ().

Raízes são um pouco especial ... eles podem querer manter as informações pertinentes para toda a árvore, e que você pode gostar uma maneira simples de olhar para cima raízes particulares e armazenar dados extras. Você pode fazer isso com um modelo que tem um relacionamento um-para-um com um nó raiz (talvez com o método salvar sobrecarregado e verificação para confirmar que o nó que aponta para is_root () antes de permitir que a salvar).

Meu ponto é geral que você pode não precisar ficar muito fantasia para fazer o que quiser. A distinção que você está fazendo já é encapsulado no conceito da árvore e sua API e você provavelmente poderia implementar um comportamento diferente com os mesmos dados básicos, verificando o contexto do nó.

Respondeu 03/12/2009 em 02:13
fonte usuário

votos
0

Se uma estrutura de árvore é uma parte integrante do seu aplicativo, considere usar algo mais do que um banco de dados relacional. Talvez Neo4j?

Respondeu 18/12/2010 em 19:53
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more