Buduję podstawowy CMS w kolbie dla strony zorientowanej na iPhone'a i mam z tym trochę problemów. Mam bardzo małą bazę danych z tylko jednym stołem (strony). Oto model:Tworzenie drzewa z samodzielnych tabel referencyjnych w SQLalchemy
class Page(db.Model):
__tablename__ = 'pages'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
parent_id = db.Column(db.Integer, db.ForeignKey("pages.id"), nullable=True)
Jak widać, do podstron, po prostu odwołać się inny obiekt strony w polu parent_id
. W panelu administracyjnym próbuję wykonać zagnieżdżoną listę nieuporządkowaną z wszystkimi stronami zagnieżdżonymi na stronach nadrzędnych. Nie mam zielonego pojęcia, jak to zrobić. Wszystko, co mogę myśleć jest następujący (które działa tylko (może, nie mam go testowane) 2 poziomy w dół):
pages = Page.query.filter_by(parent_id=None)
for page in pages:
if Page.query.filter_by(parent_id=page.id):
page.sub_pages = Page.query.filter_by(parent_id=page.id)
bym to po prostu sformatować go na liście w szablonie. Jak mogę to zrobić z potencjalnie ponad 10 zagnieżdżonymi stronami?
Dzięki temu stosy z góry!
EDIT: Mam rozejrzał się trochę i znaleźć http://www.sqlalchemy.org/docs/orm/relationships.html#adjacency-list-relationships, więc dodałem
children = db.relationship("Page", backref=db.backref("parent", remote_side=id))
do głębi Page
modelu. i patrzę na rekursywne przeglądanie wszystkiego i dodawanie go do drzewa obiektów. Ja chyba nie ma sensu, ale to najlepszy sposób mogę opisać
EDIT 2: miałem iść na dokonanie rekurencyjną funkcję uruchamiania poprzez wszystkich stron i generują duży zagnieżdżonego słownika ze wszystkich stron i ich dzieci, ale zawiesza się Pythona, więc myślę, że to jest po prostu nieskończona pętla ... oto funkcja
def get_tree(base_page, dest_dict):
dest_dict = { 'title': base_page.title, 'content': base_page.content }
children = base_page.children
if children:
dest_dict['children'] = {}
for child in children:
get_tree(base_page, dest_dict)
else:
return
a strona jestem sprawdzając je za pomocą:
@app.route('/test/')
def test():
pages = Page.query.filter_by(parent_id=None)
pages_dict = {}
for page in pages:
get_tree(page, pages_dict)
return str(pages_dict)
ktoś ma jakieś pomysły?
Dziękuję za to, ale wciąż jest trochę ponad moją głową. dla drugiego linku jest tam wak, aby to zrobić z deklaratywną podstawową metodą definiowania modeli (to jest to, czego używa rozszerzenie kostki do sqlalchemy)? –
@Estin To joinload_all call określa "dzieci" N razy. W tym przypadku 4, a więc drzewo będzie rekursować tylko 4 razy. Czy istnieje sposób na jej powtarzanie dowolną ilość razy? Chyba że istnieje programowy sposób na łatwe określenie? –
@Zoran, jeśli zaplanowałeś pracę z rekurencjami drzew, nie jest to najlepszy wybór, bardziej wydajne jest używanie rozwiązań MPTT, takich jak http://sqlalchemy-mptt.readthedocs.org/en/latest/ > O ile nie jest programowany sposób na łatwe określenie? - Możesz przechowywać na głównym węźle jego "głęboki poziom". – estin