Как отобразить несколько представлений в шаблоне проекта Django?

У меня есть проект Django с несколькими приложениями, и я хотел бы управлять шаблоном из корневой папки проекта.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        "DIRS": [os.path.join(BASE_DIR, "templates")],
        'APP_DIRS': True,
        'OPTIONS': {...}
    }]

На главной странице index.html проекта я пытаюсь вывести num_exchanges и num_accounts, сгенерированные в views.py из app1 и app2. Проблема в том, что печатается только num_exchanges, а не вторая переменная. Если переключить include в urlpatterns, то генерируется вторая переменная, а не первая.

Как я могу вывести обе переменные?

urls.py (проект)

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r"^", include("app1.urls"), name='app1'),
    url(r"^", include("app2.urls"), name='app2'),
]

index.html (проект)

{% load static %}
{% block content %}
  <h2>Stats</h2>
  <ul>
    <li><strong>Exchanges:</strong> {{ num_exchanges }}</li>
    <li><strong>Account:</strong> {{ num_accounts }}</li>
  </ul>
{% endblock %}

views.py (app1)

from django.shortcuts import render
from app1.models import Exchange


def app1_stats(request):
    num_exchanges = Exchange.objects.count()

    context = {
        'num_exchanges': num_exchanges
    }
    return render(request, 'index.html', context=context)

urls.py (app1)

from django.urls import path
from app1.views import app1_stats


urlpatterns = [
    path('', app1_stats, name='index'),
]

views.py (app2)

from django.shortcuts import render
from app2.models import Account


def app2_stats(request):
    num_accounts = Account.objects.count()

    context = {
        'num_accounts': num_accounts
    }
    return render(request, 'index.html', context=context)

urls.py (app2)

from django.urls import path
from app2.views import app2_stats


urlpatterns = [
    path('', app2_stats, name='index'),
]

Вам придется написать новое представление, которое загружает обе переменные. Django поддерживает только одно представление на загрузку страницы.

Это представление может вызывать оба других представления. Чтобы это работало, вам нужно заменить render на TemplateResponse для обоих представлений статистики.

def combined_stats(request):
    response1 = app1_stats(request)
    response2 = app2_stats(request)
    return render('index.html', {
        **response1.context_data,
        **response2.context_data
    })

Лично я бы рассмотрел возможность получения контекстных данных для app1_stats и app2_stats в функциях вне представления, которые можно вызвать в combined_stats.

def combined_stats(request):
    return render('index.html', {
        **get_app1_stats_context(),
        **get_app2_stats_context()
    })

Крайней альтернативой может быть создание context processor для двух приложений. Это сделает контекст доступным (и выполнит два дополнительных запроса) на каждой странице вашего сайта. Я бы не рекомендовал этого делать, но думаю, что это вариант, если вам нужно четко разграничить два приложения.

Вернуться на верх