[PYTHON] Ajouter le context_processor d'origine

Cet article est l'article du 25ème jour du Calendrier de l'Avent Django 2016.

Je suis désolé pour les bases du dernier jour, mais comme je ne l'ai jamais ajouté moi-même, je vais écrire sur l'étude et l'implémentation de context_processors.

Non, Python 3.6 est sorti!

** Ce qui est écrit dans cet article **: Comment ajouter des processeurs contextuels, exemple d'implémentation ** Ce que j'écris dans cet article **: Comportement à l'intérieur de context_processors

Déclencheur

Pour le moment, le site que je développe est complètement réactif à l'écriture de modèles, mais maintenant je dois séparer certains des modèles pour mobile et PC.

J'ai donc essayé d'utiliser django-mobile, mais ce n'était pas encore compatible avec Django 1.10. Il y avait aussi un moyen d'obtenir la demande d'extraction par moi-même, mais je n'avais pas beaucoup de temps et je n'avais pas à faire cela difficile, alors j'ai décidé de l'implémenter moi-même. Je n'ai jamais utilisé context_processors, j'ai donc commencé par lire le document. C'était vraiment facile.

django-mobile dispose également d'un middleware, mais je n'en avais pas besoin cette fois-ci, j'ai donc étudié uniquement les context_processors.

Qu'est-ce que context_processors

Il vous permet d'utiliser des variables sur le modèle sans avoir à les passer directement depuis la vue.

la mise en oeuvre

Par défaut, TEMPLATES dans settings.py devrait (probablement) ressembler à ceci:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]

Voici le contenu de django / templates / context_processors.py. Puisqu'il est long, je l'omets au milieu.

django/templates/context_processors.py



"""
A set of request processors that return dictionaries to be merged into a
template context. Each function takes the request object as its only parameter
and returns a dictionary to add to the context.

These are referenced from the 'context_processors' option of the configuration
of a DjangoTemplates backend and used by RequestContext.
"""

from __future__ import unicode_literals

import itertools

from django.conf import settings
from django.middleware.csrf import get_token
from django.utils.encoding import smart_text
from django.utils.functional import SimpleLazyObject, lazy


def csrf(request):
    """
    Context processor that provides a CSRF token, or the string 'NOTPROVIDED' if
    it has not been provided by either a view decorator or the middleware
    """
    def _get_val():
        token = get_token(request)
        if token is None:
            # In order to be able to provide debugging info in the
            # case of misconfiguration, we use a sentinel value
            # instead of returning an empty dict.
            return 'NOTPROVIDED'
        else:
            return smart_text(token)

    return {'csrf_token': SimpleLazyObject(_get_val)}

"""
Omis en chemin
"""

def request(request):
    return {'request': request}

Si vous spécifiez le chemin de la fonction dans context_processors de TEMPLATES ci-dessus, vous pouvez appeler la fonction dans le modèle et utiliser la valeur de retour sur le modèle. Vous n'êtes pas obligé de le passer explicitement de la vue au modèle.

Il convient de noter ici que même si vous créez une fonction appelée hoge avec context_processors, vous ne pouvez pas appeler hoge avec un modèle. Tout comme lorsque vous passez une variable d'une vue à un modèle, vous pouvez spécifier la variable et le contenu avec le nom souhaité avec dict et le renvoyer, et vous pouvez vous référer à la clé de ce dict avec le modèle. Par conséquent, lorsque la fonction suivante hoge est incluse dans context_processors, fuga est référencée sur le modèle et la chaîne fugafuga peut être utilisée sur le modèle.

Définition

def hoge(request):
    return {"fuga": "fugafuga"}

référence

{{ fuga }}

Par conséquent, pour csrf fourni par défaut, vous appellerez csrf_token comme dans django / templates / context_processors.py au lieu de csrf.

{% csrf_token %}

Mise en garde

Le settings.py ci-dessus ne charge pas `` 'django.template.context_processors.csrf', `, mais csrf est traité spécialement et est configuré pour être chargé par défaut dans les emplacements suivants.

django/template/context.py



# Hard-coded processor for easier use of CSRF protection.
_builtin_context_processors = ('django.template.context_processors.csrf',)

django/template/engine.py


class Engine(object):
    """
réduction
    """

    @cached_property
    def template_context_processors(self):
        context_processors = _builtin_context_processors
        context_processors += tuple(self.context_processors)
        return tuple(import_string(path) for path in context_processors)
    """
réduction
    """

Essayez de le mettre en œuvre vous-même

Comme je l'ai écrit au début, je veux faire la même chose que django-mobile, donc j'ajouterai un context_processor qui détermine s'il s'agit d'un smartphone à partir des informations d'agent utilisateur incluses dans la demande et renvoie True ou False.

Celles que j'ai faites sont les suivantes. Mecha est facile w

app/context_processors.py



import re
MOBILE_REGEXP = re.compile(r"Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone|IEMobile|Opera Mini|WILLCOM")

def is_mobile(request):
    is_mobile = False
    if MOBILE_REGEXP.search(request.META['HTTP_USER_AGENT']) is not None:
        is_mobile = True
    return {"is_mobile": is_mobile}

Ajoutez ʻapp.context_processors.is_mobile à context_processors` dans TEMPLATES.

settings.py


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
                'app.context_processors.is_mobile',  #cette
            ],
        },
    },
]

Et utilisez-le de la manière suivante.

{% if is_mobile == True %}
<p>Accès depuis mobile</p>
{% else %}
<p>Accès depuis le PC</p>
{% endif %}

Résumé

J'ai trouvé très facile d'ajouter context_processor. J'ai seulement étudié comment le mettre en œuvre, donc si j'ai le temps, j'aimerais bien étudier le fonctionnement interne.

finalement

J'ai été très surpris de ne pas m'attendre à ce que le calendrier de l'Avent de Django se remplisse aussi loin. Beaucoup de gens étaient en charge de plusieurs jours, et merci beaucoup!

J'avais moi-même encore beaucoup de messages de base au niveau débutant, alors j'espère pouvoir écrire quelque chose d'un peu plus haut cette fois l'année prochaine! (Ce n'est pas bon pour l'entreprise de le développer croustillant ...!)

L'année prochaine, j'espère que Django sera plus excitant au Japon que cette année, et j'aimerais conclure le dernier jour du calendrier de l'Avent. Tout le monde, profitez de Noël! !! (Vomissements) & Bonne année! !! !!

Recommended Posts

Ajouter le context_processor d'origine
Préparation du chargement du jeu de données d'origine
Exécutez le YOLO original avec Jetson Nano
Dans Jupyter, ajoutez IPerl au noyau.
Ajouter une couche à l'aide du backend Keras
Ajouter des lignes et du texte sur l'image