TemplateView
Si vous créez un service Web, la majeure partie du traitement du serveur charge un modèle HTML et lui applique des variables d'affichage.
TemplateView (django.views.generic.base.TemplateView) est fourni par Django à cet effet. Bien que ce soit une classe simple, c'est une classe de vue très pratique qui contient les fonctions requises pour la génération de page.
Si vous créez une vue au format de vue basé sur les classes, la plupart des vues HTTP GET du navigateur seront écrites dans TemplateView.
Dans le cas de POST, je pense qu'il existe de nombreux processus tels que l'utilisation de FormView, le traitement avec une vue brute et le retour de HttpResponseRedirect. (Cela dépend du contenu du service)
TemplateView peut être écrit dans divers modèles en raison des caractéristiques du langage de Python. Laquelle est la meilleure est au cas par cas, mais j'écrirai quelques-unes des méthodes que j'écris souvent.
+ manage.py
+ myapp
+ models.py
+ urls.py
+ views.py
+ templates
+ myapp
+ index.html
Supposons que vous ayez ce type de structure de répertoires.
Supposons également que settings.INSTALLED_APPS
contient myapp
et que settings.TEMPLATE_LOADERS
contient django.template.loaders.app_directories.Loader
.
Non limité à TemplateView
, il s'agit d'une fonction de View
( django.views.generic.base.View
), mais il a une fonction pour stocker automatiquement l'argument mot-clé donné au constructeur dans la variable d'instance. Lors de la conversion en fonction de vue avec ʻas_view () , tous les arguments de ʻas_view ()
sont généralement les arguments du constructeur de la classe de vue.
Et parce que TemplateView
utilise la variable d'instance nom_modèle
comme modèle par défaut,
urls.py
urlpatterns = [
url(r'^myapp/$', TemplateView.as_view(template_name='myapp/index.html'),
name='myapp-index'),
...
Si vous écrivez ceci, lorsque vous demandez myapp / dans le navigateur, le contenu de myapp / index.html sera évalué et affiché dans le navigateur.
ʻAs_view () Lorsqu'elle est exécutée, une fonction de vue encapsulée comme un décorateur est générée, mais l'argument mot-clé y est lié, et lorsque l'utilisateur le demande réellement,
TemplateView (template_name = 'myapp / index. " html ') ʻun traitement de construction équivalent fonctionne, la méthode get fonctionne et une réponse est créée.
En tant que fonction de TemplateView ou ContextMixin, la classe de vue instanciée est utilisée comme argument de modèle nommé view.
urls.py
urlpatterns = [
url(r'^myapp/a/$', TemplateView.as_view(template_name='myapp/index.html', mode='a'),
name='myapp-a'),
url(r'^myapp/b/$', TemplateView.as_view(template_name='myapp/index.html', mode='b'),
name='myapp-b'), ...
Gardez-le dans des URL comme celle-ci et utilisez le modèle
myapp/index.html
{% if view.mode == 'a' %}
Affichage du mode A
{% elif view.mode == 'b' %}
Affichage du mode B
{% endif %}
Vous pouvez également dériver l'affichage de cette manière.
De plus, en fonction de View, request, kwargs, etc. sont automatiquement ajoutés à l'argument d'instance, donc
urls.py
urlpatterns = [
url(r'^myapp/(?P<mode_name>\w+)/$', TemplateView.as_view(template_name='myapp/index.html'),
name='myapp-index'),
...
myapp/index.html
{{ view.kwargs.mode_name }}mode<br />
Bonjour! {{ view.request.user.username }}
Ce type d'affichage peut être réalisé avec juste un modèle sans écrire de code Python autre que des URL.
Ce modèle est souvent utilisé lorsque vous souhaitez écrire le traitement des vues de manière procédurale.
myapp/views.py
class IndexView(TemplateView):
template_name = 'myapp/index.html'
def get(self, request, **kwargs):
Traitement procédural...
context = {
'items': ....
}
return self.render_to_response(context)
Le processus est intuitif et facile à comprendre.
Lorsqu'il s'agit d'un traitement compliqué, la méthode devient longue verticalement, donc dans un tel cas, il est préférable d'envoyer le traitement à une autre classe. En ce qui concerne les modèles, je pense que cela fonctionne généralement bien si vous mettez des méthodes dans le modèle ou dans le gestionnaire de modèles (MyAppModel.objects ← ce type).
Pour un exemple d'extension du gestionnaire de modèles et des méthodes de génération, AbstractUser dans django.contrib.auth.models utilise UserManager comme gestionnaire.
En passant, si vous écrivez comme indiqué ci-dessus, vous ne pourrez pas faire référence à l'instance de vue dans la vue à partir du modèle, donc si vous souhaitez faire référence à la vue à partir du modèle
context = {
'view': self,
'items': ....
}
Vous pouvez également inclure explicitement la vue de cette manière.
Personnellement, quand je veux remplacer la méthode get de TemplateView, je pense que je devrais me calmer et réfléchir à ce dont j'ai vraiment besoin. Si vous souhaitez obtenir une instance de modèle, vous pouvez rendre chaque processus fragmenté et réduire le risque d'effets secondaires du processus en remplaçant get_context_data décrit plus loin ou en créant une méthode en vue.
myapp/views.py
class IndexView(TemplateView):
template_name = 'myapp/index.html'
def get(self, request, **kwargs):
if XXX:
return HttpResponseBadRequest(...)
return super().get(request, **kwargs)
# python2: return super(IndexView, self).get(request, **kwargs)
C'est une forme plus familière dans les langages orientés objet. Ce n'est pas un modèle de jouer avec le contexte du modèle, il a donc des capacités limitées et des utilisations limitées. Il est souvent utilisé lorsque vous souhaitez écrire uniquement le processus qui renvoie une erreur à la requête.
Si le remplacement de get ne semble pas être une logique sale, c'est une bonne idée de remplacer la méthode ContextMixin get_context_data.
myapp/views.py
class IndexView(TemplateView):
template_name = 'myapp/index.html'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['items'] = ...
ctx[xxx] = ...
return ctx
Ça ressemble à ça.
Si vous souhaitez créer une classe de base qui étend TemplateView, puis l'étendre (hériter en plusieurs étapes) pour créer une classe de vue réelle, il est plus simple d'écrire pour remplacer get_context_data plutôt que de remplacer get. J'ai l'impression de pouvoir le lire.
Désormais, contrairement à la substitution de get, il semble que vous ne puissiez pas accéder à l'argument de la requête, mais à cause de la fonctionnalité View, la requête concerne les variables d'instance.
myapp/views.py
class IndexView(TemplateView):
template_name = 'myapp/index.html'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['authenticated'] = self.request.user.is_authenticated
ctx[xxx] = self.request.session.get(...)
return ctx
De cette façon, vous pouvez traiter les demandes sans aucun problème.
L'argument kwargs de get_context_data contient le contenu qui correspond à l'espace réservé de l'expression régulière nommée spécifiée dans urls.py, mais ce contenu est également inclus dans self.kwargs et est accessible, il est donc un peu redondant. J'en ai envie.
La classe View fonctionne très bien avec cached_property
(django.utils.functional.cached_property) car elle est instanciée sur demande.
myapp/views.py
class IndexView(TemplateView):
template_name = 'myapp/index.html'
@cached_property
def items(self):
"""Liste des objets possédés"""
return Item.objects.filter(user=self.request.user)
@cached_property
def power_total(self):
"""Pouvoir total"""
return sum(i.power for i in self.items)
@cached_property
def power_average(self):
"""Puissance moyenne"""
return self.power_total / len(self.items)
def _get_special_items(self):
"""Générateur qui extrait uniquement les éléments spéciaux des éléments"""
for item in self.items:
if item.is_not_special:
continue
if ....:
continue
yield item
@cached_property
def special_power_total(self):
"""Puissance totale des objets spéciaux"""
return sum(i.power for i in self._get_special_items())
@cached_property
def special_power_rate(self):
"""Rapport de puissance totale des articles spéciaux et de tous les articles"""
return self.special_power_total / self.power_total
myapp/index.html
Pouvoir total: {{ view.power_total }}
Puissance spéciale totale: {{ view.special_power_total }}
Tarif spécial: {{ view.special_power_rate }}
Eh bien, dans cet exemple, il est dit que ** Créez une classe séparée qui résume les éléments sans l'écrire dans la vue! **, mais vous pouvez l'écrire comme ceci à titre d'exemple.
L'utilisation de cached_property garantit qu'un traitement intensif ne s'exécutera qu'une seule fois dans la vue sans aucune attention particulière, ce qui lui confère une bonne visibilité et une bonne vitesse de traitement. Vous n'avez pas à vous soucier de la relation hiérarchique du traitement.
Par exemple, dans cet exemple, la méthode items a @ cached_property
, donc le SQL pour rechercher le modèle Item n'est émis qu'une seule fois, et le processus de sommation de la somme des puissances de tous les éléments n'est effectué qu'une seule fois. Je comprends.
Je pense que c'est une façon d'écrire du code semblable à Python, mais qu'en est-il?
La meilleure façon de mettre en cache les résultats de la génération HTML dans un cache commun est d'utiliser le décorateur django.views.decorators.cache_page
, comme le dit la documentation Django.
Parce que vous pouvez décorer le résultat de as_view
urls.py
urlpatterns = [
url(r'^myapp/(?P<mode_name>\w+)/$',
cache_page(3600)(TemplateView.as_view(template_name='myapp/index.html')),
name='myapp-index'),
...
Ample
views.py
class IndexView(TemplateView):
template_name = 'myapp/index.html'
....
index_view = cache_page(3600)(IndexView.as_view())
urls.py
urlpatterns = [
url(r'^myapp/(?P<mode_name>\w+)/$',
'index_view',
name='myapp-index'),
...
Je pense que c'est un modèle que j'utilise souvent. login_required est le même.
views.py
class MyPageView.as_view(TemplateView):
template_name = 'mypage/index.html'
....
mypage_view = login_required(MyPageView.as_view())
Si vous utilisez django.utils.decorators.method_decorator, il transformera la fonction de décorateur afin qu'elle puisse être appliquée à la méthode liée.
views.py
class IndexView(TemplateView):
template_name = 'myapp/index.html'
@method_decorator(cache_page(3600))
def get(....):
....
C'est également une bonne idée si vous souhaitez décorer la méthode get.
Si vous n'aimez pas redéfinir la méthode get, vous pouvez le faire dans la commande as_view remplacée.
views.py
class IndexView(TemplateView):
template_name = '...'
@classonlymethod
def as_view(cls, **initkwargs):
return cache_page(3600)(
super().as_view(**initkwargs)
Dans une application Web qui renvoie du HTML, si vous êtes sur le point d'écrire un def post (...)
dans unTemplateView
, calmons-nous.
Peut-être que FormView est meilleur que TemplateView.
FormView a une fonction qui fonctionne avec le formulaire de Django pour «vous inviter à ressaisir tout en affichant un affichage d'erreur lorsqu'il y a une erreur dans le formulaire». "S'il n'y a pas d'erreur dans le formulaire, effectuez un ◯◯ traitement" est également préparé comme méthode modèle. Pourquoi n'y pensez-vous pas?
J'ai écrit sur CRUD Generic View sur mon blog. Vues génériques CRUD de Django faciles à utiliser (ListView, DetailView, CreateView, UpdateView, DeleteView)
Recommended Posts