最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Django中使用 Closure Table 儲存無限分級數(shù)據(jù)

 更新時間:2019年06月06日 14:20:52   作者:棲遲于一丘  
對于數(shù)據(jù)量大的情況(比如用戶之間有邀請鏈,有點三級分銷的意思),就要用到 closure table 的結(jié)構(gòu)來進(jìn)行存儲。這篇文章主要介紹了Django中使用 Closure Table 儲存無限分級數(shù)據(jù),需要的朋友可以參考下

這篇文章給大家介紹Django中使用 Closure Table 儲存無限分級數(shù)據(jù),具體內(nèi)容如下所述:

起步

對于數(shù)據(jù)量大的情況(比如用戶之間有邀請鏈,有點三級分銷的意思),就要用到 closure table 的結(jié)構(gòu)來進(jìn)行存儲。那么在 Django 中如何處理這個結(jié)構(gòu)的模型呢?

定義模型

至少是要兩個模型的,一個是存儲分類,一個儲存分類之間的關(guān)系:

class Category(models.Model):
 name = models.CharField(max_length=31)
 def __str__(self):
 return self.name
class CategoryRelation(models.Model):
 ancestor = models.ForeignKey(Category, null=True, related_name='ancestors', on_delete=models.SET_NULL, db_constraint=False, verbose_name='祖先')
 descendant = models.ForeignKey(Category,null=True, related_name='descendants', on_delete=models.SET_NULL,
   db_constraint=False, verbose_name='子孫')
 distance = models.IntegerField()
 class Meta:
 unique_together = ("ancestor", "descendant")

數(shù)據(jù)操作

獲得所有后代節(jié)點

class Category(models.Model):
 ...
 def get_descendants(self, include_self=False):
 """獲得所有后代節(jié)點"""
 kw = {
 'descendants__ancestor' : self
 }
 if not include_self:
 kw['descendants__distance__gt'] = 0
 qs = Category.objects.filter(**kw).order_by('descendants__distance')
 return qs獲得直屬下級
class Category(models.Model):
 ...
 def get_children(self):
 """獲得直屬下級"""
 qs = Category.objects.filter(descendants__ancestor=self, descendants__distance=1)
 return qs

節(jié)點的移動

節(jié)點的移動是比較難的,在 [ https://www.percona.com/blog/2011/02/14/moving-subtrees-in-closure-table/][1 ] 中講述了,利用django能夠執(zhí)行原生的sql語句進(jìn)行:

def add_child(self, child):
 """將某個分類加入本分類,"""
 if CategoryRelation.objects.filter(ancestor=child, descendant=self).exists() \
 or CategoryRelation.objects.filter(ancestor=self, descendant=child, distance=1).exists():
 """child不能是self的祖先節(jié)點 or 它們已經(jīng)是父子節(jié)點"""
 return
 # 如果表中不存在節(jié)點自身數(shù)據(jù)
 if not CategoryRelation.objects.filter(ancestor=child, descendant=child).exists():
 CategoryRelation.objects.create(ancestor=child, descendant=child, distance=0)
 table_name = CategoryRelation._meta.db_table
 cursor = connection.cursor()
 cursor.execute(f"""
 DELETE a
 FROM
 {table_name} AS a
 JOIN {table_name} AS d ON a.descendant_id = d.descendant_id
 LEFT JOIN {table_name} AS x ON x.ancestor_id = d.ancestor_id
 AND x.descendant_id = a.ancestor_id
 WHERE
 d.ancestor_id = {child.id}
 AND x.ancestor_id IS NULL;
 """)
 cursor.execute(f"""
 INSERT INTO {table_name} (ancestor_id, descendant_id, distance)
 SELECT supertree.ancestor_id, subtree.descendant_id,
 supertree.distance+subtree.distance+1
 FROM {table_name} AS supertree JOIN {table_name} AS subtree
 WHERE subtree.ancestor_id = {child.id}
 AND supertree.descendant_id = {self.id};
 """)

 節(jié)點刪除

節(jié)點刪除有兩種操作,一個是將所有子節(jié)點也刪除,另一個是將自己點移到上級節(jié)點中。

擴(kuò)展閱讀

[ https://www.percona.com/blog/2011/02/14/moving-subtrees-in-closure-table/][2 ]
[ http://technobytz.com/closure_table_store_hierarchical_data.html][3 ]

完整代碼

class Category(models.Model):
name = models.CharField(max_length=31)
def __str__(self):
 return self.name
def get_descendants(self, include_self=False):
 """獲得所有后代節(jié)點"""
 kw = {
 'descendants__ancestor' : self
 }
 if not include_self:
 kw['descendants__distance__gt'] = 0
 qs = Category.objects.filter(**kw).order_by('descendants__distance')
 return qs
def get_children(self):
 """獲得直屬下級"""
 qs = Category.objects.filter(descendants__ancestor=self, descendants__distance=1)
 return qs
def get_ancestors(self, include_self=False):
 """獲得所有祖先節(jié)點"""
 kw = {
 'ancestors__descendant': self
 }
 if not include_self:
 kw['ancestors__distance__gt'] = 0
 qs = Category.objects.filter(**kw).order_by('ancestors__distance')
 return qs
def get_parent(self):
 """分類僅有一個父節(jié)點"""
 parent = Category.objects.get(ancestors__descendant=self, ancestors__distance=1)
 return parent
def get_parents(self):
 """分類僅有一個父節(jié)點"""
 qs = Category.objects.filter(ancestors__descendant=self, ancestors__distance=1)
 return qs
def remove(self, delete_subtree=False):
 """刪除節(jié)點"""
 if delete_subtree:
 # 刪除所有子節(jié)點
 children_queryset = self.get_descendants(include_self=True)
 for child in children_queryset:
 CategoryRelation.objects.filter(Q(ancestor=child) | Q(descendant=child)).delete()
 child.delete()
 else:
 # 所有子節(jié)點移到上級
 parent = self.get_parent()
 children = self.get_children()
 for child in children:
 parent.add_chile(child)
 # CategoryRelation.objects.filter(descendant=self, distance=0).delete()
 CategoryRelation.objects.filter(Q(ancestor=self) | Q(descendant=self)).delete()
 self.delete()
def add_child(self, child):
 """將某個分類加入本分類,"""
 if CategoryRelation.objects.filter(ancestor=child, descendant=self).exists() \
 or CategoryRelation.objects.filter(ancestor=self, descendant=child, distance=1).exists():
 """child不能是self的祖先節(jié)點 or 它們已經(jīng)是父子節(jié)點"""
 return
 # 如果表中不存在節(jié)點自身數(shù)據(jù)
 if not CategoryRelation.objects.filter(ancestor=child, descendant=child).exists():
 CategoryRelation.objects.create(ancestor=child, descendant=child, distance=0)
 table_name = CategoryRelation._meta.db_table
 cursor = connection.cursor()
 cursor.execute(f"""
 DELETE a
 FROM
 {table_name} AS a
 JOIN {table_name} AS d ON a.descendant_id = d.descendant_id
 LEFT JOIN {table_name} AS x ON x.ancestor_id = d.ancestor_id
 AND x.descendant_id = a.ancestor_id
 WHERE
 d.ancestor_id = {child.id}
 AND x.ancestor_id IS NULL;
 """)
 cursor.execute(f"""
 INSERT INTO {table_name} (ancestor_id, descendant_id, distance)
 SELECT supertree.ancestor_id, subtree.descendant_id,
 supertree.distance+subtree.distance+1
 FROM {table_name} AS supertree JOIN {table_name} AS subtree
 WHERE subtree.ancestor_id = {child.id}
 AND supertree.descendant_id = {self.id};
 """)class CategoryRelation(models.Model): ancestor = models.ForeignKey(Category, null=True, related_name='ancestors', on_delete=models.SET_NULL, db_constraint=False, verbose_name='祖先') descendant = models.ForeignKey(Category,null=True, related_name='descendants', on_delete=models.SET_NULL, db_constraint=False, verbose_name='子孫') distance = models.IntegerField()
class Meta:
 unique_together = ("ancestor", "descendant")[1]: https://www.percona.com/blog/2011/02/14/moving-subtrees-in-closure-table/
 [2]: https://www.percona.com/blog/2011/02/14/moving-subtrees-in-closure-table/
 [3]: http://technobytz.com/closure_table_store_hierarchical_data.html

總結(jié)

以上所述是小編給大家介紹的Django中使用 Closure Table 儲存無限分級數(shù)據(jù),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Python+Selenium自動化實現(xiàn)分頁(pagination)處理

    Python+Selenium自動化實現(xiàn)分頁(pagination)處理

    這篇文章主要為大家詳細(xì)介紹了Python+Selenium自動化實現(xiàn)分頁pagination處理的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • python中字符串前面加r的作用

    python中字符串前面加r的作用

    這篇文章主要介紹了python中字符串前面加r的作用,實例分析了Python通過字符串前面加r實現(xiàn)禁止字符串轉(zhuǎn)義的功能,需要的朋友可以參考下
    2015-06-06
  • python自動化測試之連接幾組測試包實例

    python自動化測試之連接幾組測試包實例

    這篇文章主要介紹了python自動化測試之連接幾組測試包實例,需要的朋友可以參考下
    2014-09-09
  • Python tensorflow與pytorch的浮點運算數(shù)如何計算

    Python tensorflow與pytorch的浮點運算數(shù)如何計算

    這篇文章主要介紹了Python tensorflow與pytorch的浮點運算數(shù)如何計算,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-11-11
  • python搜索包的路徑的實現(xiàn)方法

    python搜索包的路徑的實現(xiàn)方法

    今天小編就為大家分享一篇python搜索包的路徑的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • Python繪圖之實現(xiàn)繪制極坐標(biāo)圖像

    Python繪圖之實現(xiàn)繪制極坐標(biāo)圖像

    這篇文章主要介紹了如何利用python繪制極坐標(biāo)圖像,文中的示例代碼講解詳細(xì),具有一定的的參考價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-08-08
  • python selenium 查找隱藏元素 自動播放視頻功能

    python selenium 查找隱藏元素 自動播放視頻功能

    這篇文章主要介紹了python selenium 查找隱藏元素 自動播放視頻功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-07-07
  • OpenCV-Python直方圖均衡化實現(xiàn)圖像去霧

    OpenCV-Python直方圖均衡化實現(xiàn)圖像去霧

    直方圖均衡化可以達(dá)到增強(qiáng)圖像顯示效果的目的。最常用的比如去霧。本文就來實現(xiàn)直方圖均衡化實現(xiàn)圖像去霧,感興趣的可以了解一下
    2021-06-06
  • Python上下文管理器深入講解

    Python上下文管理器深入講解

    Python有三大神器,一個是裝飾器,一個是迭代器、生成器,最后一個就是今天文章的主角 -- 「上下文管理器」。上下文管理器在日常開發(fā)中的作用是非常大的,可能有些人用到了也沒有意識到這一點
    2022-12-12
  • django執(zhí)行原始查詢sql,并返回Dict字典例子

    django執(zhí)行原始查詢sql,并返回Dict字典例子

    這篇文章主要介紹了django執(zhí)行原始查詢sql,并返回Dict字典例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04

最新評論

清水县| 丹凤县| 辽阳县| 白玉县| 石景山区| 滁州市| 云浮市| 英山县| 界首市| 沙河市| 宁安市| 昭苏县| 大安市| 乳源| 达尔| 镇康县| 无锡市| 潮州市| 潞城市| 通城县| 图木舒克市| 天镇县| 丰顺县| 大同县| 阜阳市| 昭平县| 泸水县| 宁德市| 梅州市| 共和县| 海林市| 江阴市| 鄄城县| 垦利县| 陆川县| 肇庆市| 白河县| 棋牌| 历史| 博乐市| 富宁县|