2010-06-14 25 views
5

django-mptt dường như quyết tâm đẩy tôi ra khỏi tâm trí của tôi. Tôi đang cố gắng để làm một cái gì đó tương đối đơn giản: Tôi sẽ xóa một nút, và cần phải làm một cái gì đó hợp lý với trẻ em của nút. Cụ thể, tôi muốn di chuyển chúng lên một cấp độ để chúng là con của cha mẹ của cha mẹ hiện tại của chúng.django-mptt: làm thế nào để di chuyển thành công các nút xung quanh

Nghĩa là, nếu cây trông giống như:

Root 
    | 
Grandpa 
    | 
Father 
| | 
C1 C2 

tôi sẽ xóa Cha, và muốn C1 và C2 là con của ông nội.

Dưới đây là đoạn code tôi đang sử dụng:

class Node(models.Model): 
    first_name = models.CharField(max_length=80, blank=True) 
    parent  = models.ForeignKey('self', null=True, blank=True, related_name='children') 

    def reparent_children(self, parent): 
     print "Reparenting" 
     for child in self.get_children(): 
      print "Working on", child.first_name, "to parent", parent.email 
      parent = Node.objects.get(id=parent.id) 
      child.move_to(parent, 'last-child') 
      child.save() 

Vì vậy, tôi muốn gọi:

father.reparent_children(grandpa) 
father.parent = None 
father.save() 

này hoạt động - gần. Các em báo cáo các bậc phụ huynh như Grandpa:

c1.parent == grandpa # True 

Grandpa đếm C1 và C2 ở trẻ em của nó

c1 in grandpa.children.all() # True 

Tuy nhiên, gốc disowns những đứa trẻ.

c1.get_root() == father # c1's root is father, instead of Root 

c1 in root.get_descendants() # False 

Làm cách nào để các con di chuyển và thư mục gốc của chúng không bị hỏng?

+1

bạn có chắc rằng "father.parent = Không" là đúng cách để xóa một nút? – mawimawi

+0

Trong trường hợp này, tôi không thực sự xóa nút - tôi đang lưu trữ nó. Tôi muốn lấy nó ra khỏi cái cây. Bạn có một điểm tốt mặc dù, tôi không thực sự loại bỏ nó từ cây ở đây. – Parand

+0

Có vẻ như đặt cha mẹ thành Không và lưu thực sự là cách để xóa nút khỏi cây (theo các trường hợp thử nghiệm mptt), vì vậy trông có vẻ đúng. – Parand

Trả lời

6

Giá trị nội bộ lftrght sẽ thay đổi lần đầu tiên bạn lưu con (tức là dòng cuối cùng của phương thức reparent_children). save() không cập nhật các trường hợp bạn có thể đã nói dối. Tôi nghĩ một cách an toàn để làm điều này sẽ được tìm nạp lại chúng từ cơ sở dữ liệu mỗi lần, như thế này:

def reparent_children(self, parent): 
    print "Reparenting" 
    for child in self.get_children(): 
     print "Working on", child.first_name, "to parent", parent.email 
     parent = Node.objects.get(id=parent.id) 
     current_child = Node.objects.get(id = child.id) 
     current_child.move_to(parent, 'last-child') 
     current_child.save() 

tôi đã similar problems một thời gian trở lại, và cách tiếp cận giải quyết vấn đề của tôi.

+4

Dominic, tôi đã kết thúc ở phương pháp này, và nó * có vẻ * hoạt động, mặc dù với django-mptt tôi kết thúc liên tục đặt câu hỏi về sự tỉnh táo của riêng tôi.Tôi không biết nếu tôi đã thực sự cố định vấn đề hoặc ẩn nó đi nơi khác. – Parand

1

Thư viện này thực sự làm tôi bối rối trong vài ngày qua - move_to dường như không thực sự làm những gì tôi muốn, và cây của tôi không bị đồng bộ. Tôi đã đưa ra một giải pháp mà tôi tự tin hơn, với chi phí về tốc độ và sự phi truyền thống.

Nó xoay quanh phương thức của người quản lý partial_rebuildhere.

def delete_node(self): 
    if not self.parent: 
     print("Should not delete root node, confusing behavior follows") 
     return 
    tree_id = self.tree_id 
    parent = self.parent 

    for child in self.get_children(): 
     child.parent = parent 
     child.save() 

    self.delete() 
    Node.objects.partial_rebuild(tree_id) 

Bạn có thể thay child.parent = mẹ với child.move_node (mẹ) nếu bạn muốn

Các vấn đề liên quan