image
4 maja 2023

Czym jest Context proccesor in Django i jak to stosować?

4 maja 2023

W trakcie tworzenia aplikacji internetowych z wykorzystaniem Django często napotykamy sytuacje, gdy chcemy przekazać dynamiczne dane do naszych szablonów HTML. Te dane mogą pochodzić z bazy danych, plików konfiguracyjnych, zmiennych środowiskowych czy też z innych źródeł. W przypadku gdy potrzebujemy takich danych tylko w jednym konkretnym widoku, możemy je przekazać poprzez kontekst, który jest słownikiem zawierającym pary klucz-wartość. Niestety, korzystając z tego podejścia, uzyskujemy dostęp do tych danych tylko w konkretnym szablonie.

 

Jednakże, może się zdarzyć, że będziemy chcieli uzyskać dostęp do niektórych zmiennych w obrębie całego projektu. W takiej sytuacji warto zastosować Context Processor, który jest specjalną funkcją, do której dostęp będziemy mieli niezależnie od szablonu, w którym się znajdujemy. Funkcja ta przyjmuje jako argument obiekt HttpRequest, a zwraca słownik, który zostaje dodany do kontekstu szablonu.


"A context processor has a simple interface: It’s a Python function that takes one argument, an HttpRequest object, and returns a dictionary that gets added to the template context."

Django docoks

 

W tym artykule omówimy, jak tworzyć własne Context Processor w Django oraz jak korzystać z nich w praktyce, aby ułatwić sobie życie i zwiększyć elastyczność naszych aplikacji.

 

Przykład widoku z ograniczonym dostępem do danych

 

Zacznijmy od analizy sytuacji, w której mamy ograniczony dostęp do danych w naszych widokach. Weźmy za przykład aplikację, która pozwala na przeglądanie i zarządzanie kategoriami książek. W naszym uproszczonym przykładzie, widok categories_list pozwala na wyświetlenie wszystkich kategorii zapisanych w naszej bazie danych:

 

def categories_list(request):      
    all_categories = Category.objects.all()
            
    context = {
        'all_categories':all_categories,
    }

    return render(request, 'categories/categories_view.html', context)

 

Dostęp do zmiennej all_categories mamy tylko w szablonie categories_view.html. Rozwiązanie to jest poprawne, ale może być uciążliwe, jeśli chcielibyśmy wyświetlić te same dane w innych częściach naszej aplikacji. Mogłoby się wydawać, że najprostszym sposobem na rozwiązanie tego problemu jest powielanie części kodu i umieszczenie go bezpośrednio w każdym widoku. Jednak możemy to zrobić znacznie skuteczniej, korzystając z Context Processorów.

 

 

Kiedy używać context processor?

 

Context Processor warto zastosować, jeśli w projekcie chciałbyś uzyskać dostęp do wybranych danych w obrębie całej aplikacji lub w kilku widokach. Wyobraźmy sobie, że chcielibyśmy uzyskać dostęp do all_categories w pasku nawigacji (navigation bar), który wyświetla się na każdej stronie naszego projektu. Jest to prawdopodobnie jeden z najczęstszych przypadków wykorzystania dedykowanego Context Processor, jednak równie dobrze sprawdzi się, jeśli chcesz wykorzystać go do panelu bocznego (sidebar) lub stopki (footer).

 

Oprócz tego, Context Processor może być również używany do przekazywania globalnych ustawień, takich jak informacje o stronie, dane dotyczące użytkownika czy też dane statystyczne. W ten sposób możemy uporządkować nasz kod i uniknąć powtarzania tych samych fragmentów kodu w różnych miejscach.

 

Implementacja Context Processor

 

W oficjalnej dokumentacji można znaleźć informacje, że kod naszego custom context processor może zostać umieszczony w dowolnym miejscu bez konkretnych ograniczeń.

Custom context processors can live anywhere in your code base. All Django cares about is that your custom context processors are pointed to by the 'context_processors' option in your TEMPLATES setting 

Jednak dla spójności zalecam tworzyć plik context_processors.py i umieścić go wewnątrz palikacji której będzie dotyczył. W moim przypadku będzie to:

APPS\categories\context_processors.py

 

Następnie będąc już wewnątrz pliku importujemy Model oraz tworzymy funkcję:

from .models import Category

def categories_context(request):         
    all_categories = Category.objects.all()
            
    return{'all_categories':all_categories}

 

Warto zauważyć, że mimo podobieństw do klasycznego view w tym przypadku wywołanie return zwracam nam jedynie dictionary zawierający all_categories

 

Na tym etapie nasz custom context_processors jest już teoretycznie gotowy, jednak żeby móc z niego skorzystać należy go również dodać do TEMPLATES wewnątrz pliku settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [ BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',


                # our new custom context processor:
                'APPS.Books.context_processors.categories_context',
            ],
        },
    },
]

 

Teraz gdy mamy już wszystko przygotowane możemy wyświetlić all_categories w dowolnej części naszej aplikacji używając do tego kod {% category_list %} . W moim przypadku będzie to plik header.html z wykorzystaniem Bootstrap.

 

 

Wykorzystanie Context Processor w szablonie HTML

 

Od tego możmy używać naszej naszej dynamicznej zmiennej w dowolonym szablonie. W naszym przypadku chcielibyśmy dodać listę kategorii do paska nawigacji (navigation bar) z użyciem frameworku Bootstrap.

 

W pliku header.html możemy dodać następujący kod:

<header class="section-header">
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="#">Navbar</a>

        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
                <li class="nav-item active">
                    <a class="nav-link" href="#">Home</a>
                </li>

                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                        data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Categories
                    </a>

                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">

                        # using our new context proccesor

                        {% for category in category_list %}
                            <a class="dropdown-item" href="{{category.get_absolute_url}}"> 
                                {{category.category_name}}
                            </a>
                        {% endfor %}

                    </div>
                </li>

            </ul>
        </div>
    </nav>
</header> <!-- section-header.// -->

 

W powyższym fragmencie kodu HTML, wykorzystujemy nasz Context Processor do iterowania po wszystkich kategoriach książek (all_categories) i wyświetlania ich w rozwijanej liście w pasku nawigacji. Dzięki temu, lista kategorii będzie dostępna na każdej podstronie naszego projektu.

Nasz nowy Context Processor może być również wykorzystany w dowolnym innym szablonie w taki sam sposób, jak zaprezentowaliśmy powyżej.

 

Podsumowanie

 

W niniejszym artykule omówiliśmy, czym jest Context Processor w Django i jak go stosować w praktyce. Przyjrzyjmy się jeszcze raz kluczowym elementom, które omówiliśmy:

 

1. Wprowadzenie do Context Processorów w Django - przedstawiliśmy koncepcję Context Processorów jako narzędzia, które umożliwiają dostęp do zmiennych w różnych szablonach w obrębie całego projektu.

 

2. Przykład widoku z ograniczonym dostępem do danych - pokazaliśmy, jak klasyczne podejście do widoków ogranicza dostęp do danych jedynie do konkretnego szablonu.

 

3. Kiedy używać Context Processor? - wyjaśniliśmy, że warto zastosować Context Processor, gdy chcemy uzyskać dostęp do wybranych danych w obrębie całej aplikacji lub w kilku widokach.

 

4. Implementacja Context Processor - przedstawiliśmy krok po kroku, jak zaimplementować własny Context Processor, od tworzenia pliku context_processors.py, poprzez tworzenie funkcji i dodanie jej do ustawień TEMPLATES.

 

5. Wykorzystanie Context Processor w szablonie HTML z Bootstrapem - pokazaliśmy, jak użyć naszego Context Processor w praktyce, dodając listę kategorii do paska nawigacji w szablonie HTML z Bootstrapem.

 

Teraz, gdy znasz zalety korzystania z Context Processorów w Django, możesz z powodzeniem stosować te techniki w swoich projektach, aby upewnić się, że Twoje aplikacje są bardziej elastyczne, czytelne i łatwe w utrzymaniu.

Dyskusja

Twój komentarz

Tagi