2015-07-10 35 views
9

我使用的是Django的MPTT包我的意見的應用程序和我有以下型號:動態訂單

class Comment(MPTTModel): 
    content = models.TextField(verbose_name='Treść') 
    author = models.ForeignKey(AUTH_USER_MODEL, verbose_name='Autor', blank=False, null=True) 
    is_deleted = models.BooleanField(verbose_name='Komentarz usunięty', default=False, 
            help_text='Zaznacz, aby usunąć komentarz') 

    ip = models.GenericIPAddressField(default=0, verbose_name='Adres IP') 

    content_type = models.ForeignKey(ContentType, verbose_name='Typ obiektu') 
    object_id = models.PositiveIntegerField(verbose_name='ID obiektu') 
    content_object = GenericForeignKey('content_type', 'object_id') 
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True) 
    hotness = models.FloatField(default=0) 

    created_at = models.DateTimeField(auto_now_add=False, verbose_name='Data dodania') 

    updated_at = models.DateTimeField(auto_now=True, verbose_name='Aktualizacja') 

    class MPTTMeta: 
     order_insertion_by = ('-hotness', '-created_at') 

    class Meta: 
     verbose_name = 'Komentarz' 
     verbose_name_plural = 'Komentarze' 

    def __unicode__(self): 
     if len(self.content) > 50: 
      return self.content[:50] + '...' 
     else: 
      return self.content 

我想給用戶可能通過辣味或排序評論樹創建日期。是否有可能從視圖編輯order_insertion_by字段以生成2種排序(按日期,按熱度)?謝謝你的幫助。

+0

你找到關於該解決方案? –

+0

不,我沒有。 :( – Peterek

+0

我用下面的代碼示例(python3)做了一些測試,它似乎工作 - 但它會很好,如果別人會嘗試一下。 – biodiv

回答

3

Modified Preorder Tree Traversal(MPTT)是檢索樹結構,使用左一個查詢(在MPTT lft),右(rgt)編號如下所示http://sitepointstatic.com/graphics/sitepoint_numbering.gif的方式。

定義不止一個order_insertion_by將以下(根據mptts評論)做:

""" 
    Creates a filter which matches suitable right siblings for ``node``, 
    where insertion should maintain ordering according to the list of 
    fields in ``order_insertion_by``. 

    For example, given an ``order_insertion_by`` of 
    ``['field1', 'field2', 'field3']``, the resulting filter should 
    correspond to the following SQL:: 

     field1 > %s 
     OR (field1 = %s AND field2 > %s) 
     OR (field1 = %s AND field2 = %s AND field3 > %s) 

""" 

如果我理解正確的話,order_insertion_by指定的兄弟姐妹,這代表了父母的兒童(不後代)的排序元件。如果你想要兩個不同的訂單,lftrgt將不得不改變,因此它是第二棵樹。這不包括在mptt中。

你仍然可以做

Comment.objects.all().order_by('-hotness') 

,但你會失去樹結構。通常不可能維護樹結構並通過別的東西來排序整個樹,例如,辣味。想象一下,你具備以下條件:

Comment1 (hotness 0) 
    Comment2 (hotness 2, child of Comment1) 
Comment3 (hotness 1) 

這將導致

Comment2 
Comment3 
Comment1 

它是有序的,但Comment2沒有連接到Comment1。 如果要使用比order_insertion_by同級級-基礎上定義別的東西進行排序,得到如下:

Comment3 
Comment1 
    Comment2 

一個也許可以寫一個新的模板標籤一樣{% recursetree objects -hotness %}是遍歷和再 - 排序children元素並返回新的樹。它仍然是一個數據庫查詢 - 但我無法估計性能影響。

你將不得不叉MPTT和編輯mptt_tags.py如下:

class RecurseTreeNode(template.Node): 
    def __init__(self, template_nodes, queryset_var, order_var=None): 
     self.template_nodes = template_nodes 
     self.queryset_var = queryset_var 
     self.order_var = order_var 

    def _render_node(self, context, node): 
     bits = [] 
     context.push() 

     children = node.get_children() 

     if children and self.order_var is not None: 
      children = children.order_by(self.order_var)    

     for child in children: 
      bits.append(self._render_node(context, child)) 
     context['node'] = node 
     context['children'] = mark_safe(''.join(bits)) 
     rendered = self.template_nodes.render(context) 
     context.pop() 
     return rendered 

    def render(self, context): 
     queryset = self.queryset_var.resolve(context) 
     roots = cache_tree_children(queryset) 
     bits = [self._render_node(context, node) for node in roots] 
     return ''.join(bits) 


@register.tag 
def recursetree(parser, token): 
    bits = token.contents.split() 
    if len(bits) < 2: 
     raise template.TemplateSyntaxError(_('%s tag requires a queryset') % bits[0]) 

    queryset_var = template.Variable(bits[1]) 

    if len(bits) == 3: 
     order_var = bits[2] 
    else: 
     order_var = None 

    template_nodes = parser.parse(('endrecursetree',)) 
    parser.delete_first_token() 

    return RecurseTreeNode(template_nodes, queryset_var, order_var)