2015-07-10 11 views
9

używam pakiet django-mptt dla mojej aplikacji komentarze i mam następujący model to:dynamiczny porządek w 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 

Chciałbym dać możliwość obsługi do sortowania komentarz drzewa za gorąca lub Data utworzenia. Czy z pola widzenia można edytować pole order_insertion_by, aby wygenerować 2 rodzaje sortowania (według daty, według intensywności)? Dzięki za pomoc.

+0

Znalazłeś rozwiązanie na ten temat? –

+0

Nie, nie zrobiłem tego. :( – Peterek

+0

Zrobiłem kilka testów z moim przykładem kodu poniżej (python3) i wygląda na to, że działa - ALE byłoby miło, gdyby ktoś próbował to wypróbować. – biodiv

Odpowiedz

3

The Modified Preorder Tree Traversal (MPTT) jest sposób, aby odzyskać strukturę drzewa z jednym zapytania przy użyciu lewo (lft w mptt) i prawej (rgt) numerowania, jak pokazano tutaj http://sitepointstatic.com/graphics/sitepoint_numbering.gif.

Definiowanie więcej niż jednej order_insertion_by będzie wykonać następujące czynności (według mptts komentarzach):

""" 
    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) 

""" 

Jeśli rozumiem go poprawnie, order_insertion_by określa kolejność rodzeństwa, które reprezentują dzieci (nie potomków) z rodzicem element. Jeśli chcesz mieć dwa różne zamówienia, lft i rgt również musiałyby zostać zmienione, a zatem jest to drugie drzewo. To nie jest zawarte w mptt.

Można jeszcze zrobić

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

ale stracisz strukturę drzewa. Zasadniczo nie jest możliwe zachowanie struktury drzewa i uporządkowanie całego drzewa przez coś innego, np. gorliwość. Wyobraź sobie, że masz następujące:

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

co skutkowałoby

Comment2 
Comment3 
Comment1 

To jest uporządkowane, ale Comment2 nie jest dołączony do Comment1. Jeśli chcesz uporządkować za pomocą czegoś innego niż określony przez order_insertion_by na rodzeństwo-level-podstawa, aby uzyskać następujące:

Comment3 
Comment1 
    Comment2 

jeden może być w stanie napisać nowy szablon jak {% recursetree objects -hotness %} że iteracje nad i re -sorts children elementów i zwraca nowe drzewo. Wciąż jest to jedno zapytanie do bazy danych - ale nie mogę oszacować trafienia wydajności.

trzeba będzie bulić mptt i edytować mptt_tags.py następująco:

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) 
Powiązane problemy