2017-05-05 6 views
1

J'essaie de créer une vue hiérarchique dans Django, mais j'ai du mal à comprendre comment utiliser efficacement QuerySets.Création d'une vue de hiérarchie dans Django

Ce que je vise est finalement une page html qui affiche des cours comme celui-ci:

Main Course 1 --- Child Course 1 
       --- Child Course 2 

Main Course 2 --- Child Course 3 
       --- Child Course 4 

Chaque groupe de cours serait enveloppé dans un div style et etc.

À mon avis. py Je donne les résultats suivants:

class HierarchyView(generic.ListView): 
template_name = 'curriculum/hierarchy.html' 

def get_queryset(self): 
    return Offering.objects.all() 

def get_context_data(self, **kwargs): 
    context = super(HierarchyView, self).get_context_data(**kwargs) 
    context['main'] = self.get_queryset().filter(course_type='M') 
    context['sub'] = self.get_queryset().filter(parent_code__in=context['main']) 
    return context 

le modèle de placement est mis en place afin que parent_code est une clé étrangère auto-référentiel (c.-à-tout cours peut être un enfant de tout autre), comme t son:

... 
parent_code = models.ForeignKey(
    'self', 
    null=True, 
    blank=True, 
    on_delete=models.SET_NULL) 
... 

Et dans mon modèle html J'ai:

{% for mainoffering in main %} 
<div> 
<div>{{ mainoffering.course_name }}</div> 
    {% for offering in sub %} 
    <div>{{ offering.course_name }}</div> 
    {% endfor %} 
</div> 
{% endfor %} 

Ce que cela entraîne, cependant, est que tous les cours enfants apparaissent sous tous les cours principaux, que oui ou non ils sont en réalité les enfants de ce cours, ce qui n'est évidemment pas ce que je cherche. Je suis encore en train d'apprendre les ficelles du métier dans Django, et j'ai du mal à trouver quoi que ce soit qui explique en anglais ce que je dois faire. S'il vous plaît aider!

+1

ce que vous avez besoin est django-mptt – e4c5

Répondre

0

Je pense que vous auriez besoin de changer votre modèle pour correspondre à chacun des cours pour enfants à leurs cours parents. Peut-être quelque chose comme:

{% for mainoffering in main %} 
<div> 
<div>{{ mainoffering.course_name }}</div> 
    {% for offering in sub %} 
    {% if offering.parent_code == mainoffering %} 
     <div>{{ offering.course_name }}</div> 
    {% endif %} 
    {% endfor %} 
</div> 
{% endfor %} 
0

Le contexte [ « sous »] retournera tous, sans regroupement, la commande etc. Vous pouvez faire deux choses pour obtenir le comportement souhaité.

Vous pouvez faire une prélecture liée.

from django.db.models import Prefetch 

offerings = Offering.objects.filter(course_type='M').prefetch_related(
    Prefetch(
     "courses_subset", 
     queryset=Offering.objects.filter(parent_code__in=offerings), 
     to_attr="sub" 
    ) 
) 
for o in offerings:   
    print o.sub 

Vous pouvez réellement en faire une méthode dans votre modèle et créer un modèle de balise (j'utiliserais probablement ceci).

method in your Offering model

def get_child_courses(self): 
    child_courses = Offerings.objects.filter(parent_code=self.id) 
    return child_courses 

template tag

@register.simple_tag 
def get_child_courses(course): 
    return course.get_child_courses() 

Dans votre modèle:

{% for mainoffering in main %} 
<div> 
<div>{{ mainoffering.course_name }}</div> 
    {% for offering in mainoffering|get_child_course %} 
    <div>{{ offering.course_name }}</div> 
    {% endfor %} 
</div> 
{% endfor %} 

Vous pouvez les regrouper dans votre modèle comme suggéré par accraze. Je vais personnellement pour la deuxième option

+0

Merci d'avoir pris le temps d'expliquer si bien, je peux finir par utiliser votre méthode, mais la solution d'accraze a frappé le clou sur la tête! – Luke