2009-10-19 8 views
1

Peut-être une question simple, mais je viens juste de commencer à travailler avec Django après quelques années d'expérience php :-)requête complexe dans Django

Problème: nous avons une paire de modèles - « Catégories » et " Poster". "Catégories" est l'arborescence des ensembles de catégories de postes imbriqués, "Publier" est la liste simple des articles de blog avec le champ ForeignKey, lié au modèle Catégories. Voici un exemple:

class Categories(NS_Node): 

    title = models.CharField(max_length = 150) 
    slug = models.SlugField(unique = True) 

class Post(models.Model): 

    title = models.CharField(max_length = 150) 
    slug = models.SlugField(unique = True) 
    text = models.TextField() 
    category = models.ForeignKey(Categories) 

NS_Node - classe de la bibliothèque de Sylvebarbe, met en œuvre Nested définit le modèle de données.

L'utilisateur peut voir les messages pour la catégorie spécifiée en visitant la page avec des urls comme '/ books/science-fiction /'. Dans la vue django nommée "catégorie", nous devons sélectionner uniquement les publications liées à la catégorie "science fiction". Maintenant, je le fais comme ceci:

def category(request, path): 

    # 'path' is 'books/sci-fi' 
    # detect current category code from url 
    category_slug = path.split('/')[-1] 

    # get current category object 
    category = Categories.objects.get(slug = category_slug) 

    # get child categories 
    childs = category.get_descendants(); 

    # make list of id for needed categories 
    ids = [child.id for child in childs] 

    # add current category id 
    ids.append(category.id) 

    # selecting posts for current and nested categories 
    posts_list = Post.objects.filter(category__in = ids) 

Cela fonctionne, mais la voix interne dit qu'il y a des étapes inutiles dans ce code. Comment rendre ce code plus simple et plus valide, pouvez-vous le conseiller? Merci.

Répondre

6

Vous pouvez effectuer quelques optimisations.

Tout d'abord, le filtre in accepte des objets ainsi que ids, vous pouvez donc ignorer la compréhension de la liste:

categories = list(category.get_descendants) 
categories.append(category) 
Post.objects.filter(category__in=categories) 

Pour une plus grande amélioration, vous avez besoin de se salir avec la mise en œuvre des ensembles imbriqués. Je ne suis pas totalement familier avec cela, mais en regardant la documentation treebeard, il ressemble à MPTT, que je comprends. Si oui, nous pouvons compter sur le fait que les catégories que nous voulons avoir un attribut lft dont la valeur se situe entre le lft et la rgt de la catégorie actuelle de faire la chose en une seule fois:

Post.objects.filter(category__lft__range=(category.lft, category.rgt)) 
+1

+1 à l'aide les champs lft et rgt qui vous donneront finalement de meilleures performances côté SQL – Pras