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.
TEMPLATE_LOADERS
et TEMPLATE_CONTEXT_PROCESSORS
sont obsolètes dans Django 1.10.)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
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.
Il vous permet d'utiliser des variables sur le modèle sans avoir à les passer directement depuis la vue.
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 %}
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
"""
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 %}
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.
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! !! !!