Django custom function taking a long time to run for the view

I have a function below that generates a navigation so it can be using in the view. It is pulling in the articles, article category, and article subcategory. The main issue is that with about 15 category and 46 subcategory and 33 articles it is taking like 7-10 seconds to finish loading this function. What is the best approach for handling this so that it loads faster?

def generate_navigation_list(request):
    articles = Article.objects.all()
    article_category = ArticleCategory.objects.all()
    articles_sub_category = ArticleSubCategory.objects.all()
    
    # Create a navigation list structure
    navigation_list = []

    # Iterate over categories
    for category in article_category:
        category_dict = {
            'id': category.id,
            'title': category.name,
            'subcategory': []
        }

        # Filter subcategories for the current category
        filtered_subcategories = articles_sub_category.filter(category=category)

        # Iterate over filtered subcategories
        for subcategory in filtered_subcategories:
            subcategory_dict = {
                'id': subcategory.id,
                'title': subcategory.name,
                'articles': []
            }

            # Filter articles for the current subcategory
            filtered_articles = articles.filter(sub_category=subcategory).order_by('order')

            # Add articles to the subcategory dictionary if there are articles
            if filtered_articles.exists():  # Check if there are any articles
                for article in filtered_articles:
                    article_dict = {
                        'title': article.title,
                        'slug': article.slug
                    }
                    subcategory_dict['articles'].append(article_dict)

                # Append subcategory dictionary to category dictionary
                category_dict['subcategory'].append(subcategory_dict)

        # Append category dictionary to navigation list if it has subcategories with articles
        if category_dict['subcategory']:
            navigation_list.append(category_dict)

    request.session['navigation_list'] = navigation_list
    request.session.save()

In the code you wrote, you query articles for each category and subcategory. This means multiple queries are sent to the database. Instead, you can use select_related and prefetch_related to retrieve data from the database with fewer queries.

def generate_navigation_list(request):
articles = Article.objects.select_related('sub_category').all()
article_categories = ArticleCategory.objects.prefetch_related('subcategories').all()


navigation_list = []

for category in article_categories:
    category_dict = {
        'id': category.id,
        'title': category.name,
        'subcategory': []
    }

    # Iterate over subcategories
    for subcategory in category.subcategories.all():
        subcategory_dict = {
            'id': subcategory.id,
            'title': subcategory.name,
            'articles': []
        }

       
        filtered_articles = [article for article in articles if article.sub_category == subcategory]

        
        if filtered_articles:
            for article in filtered_articles:
                article_dict = {
                    'title': article.title,
                    'slug': article.slug
                }
                subcategory_dict['articles'].append(article_dict)

            
            category_dict['subcategory'].append(subcategory_dict)

    
    if category_dict['subcategory']:
        navigation_list.append(category_dict)

request.session['navigation_list'] = navigation_list
request.session.save()
Back to Top