technologies avancées · une sorte d'enveloppe de ”django-admin” l'interface...
TRANSCRIPT
Technologies avancées
Olivier Pons / 2016
Connaître les bases
Technologies avancées
Olivier Pons / 2015
Objectif
DjangoDjango
Technologies avancées
1 – Django – Installation
2 – Site basique2 – Site basique
3 / 71
Etapes qui vont suivre
Olivier Pons / 2016
1. Installation de l'environnement
2. Installation de Django
3. Création d'un projet vide
4. Création d'une application ”monblog”
Technologies avancées
1 – Django – Installation
2 – Site basique2 – Site basique
4 / 71
Création de l'environnement virtuel
mkdir monenvcd monenvpython3 -m venv myvenvmyvenv/bin/activate ←→ source bin/activatemyvenv/bin/pip install --upgrade pipmyvenv/bin/pip install django
Olivier Pons / 2016
Technologies avancées
1 – Django – Installation
2 – Site basique2 – Site basique
5 / 71
Création de l'environnement virtuel – Python 2.x
mkdir monenvcd monenvvirtualenv myvenvsource myvenv/bin/activatemyvenv/bin/pip install requestsmyvenv/bin/pip install --upgrade pipmyvenv/bin/pip install django
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
6 / 71
Création du projet
> myvenv/bin/django-admin.py startproject monprojet .> tree monprojet
monprojet/ ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py
Editez monprojet/settings.pyEt mettez le en français, avec TIMEZONE à ”Europe/Paris”
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
7 / 71
Les fichiers de base
monprojet/
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
→ Dossier racine
→ monprojet est un module
→ configuration du site Web
→ résolution des routes (urlresolver)
→ Web Server Gateway Interface = serveur
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
8 / 71
Création du projetLe fichier manage.py estune sorte d'enveloppe de ”django-admin”
L'interface d'administration n'existe pas car…elle est générée automatiquement !
En attendant il faut demander à générerla base de données dont se servent les modulesde base…
Puis générer une application.
En général : un projet, qui contient plusieurs applications
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
9 / 71
Création de la base de données
myvenv/bin/python3 manage.py migrate
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
10 / 71
Lancement du serveur
myvenv/bin/python3 manage.py runserver
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
11 / 71
Nouvelle application
>> myvenv/bin/python3 manage.py startapp monblog>> tree monblog/
monblog/ ├── __init__.py ├── admin.py ├── migrations
│ └── __init__.py ├── models.py ├── tests.py └── views.py
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
12 / 71
Nouvelle application
Ajouter dans monprojet/settings.py l'application 'monblog'
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'monblog',)
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
13 / 71
Modèle exemple
Mettre dans monblog/models.py :from django.db import modelsfrom django.utils import timezone
class Post(models.Model): author = models.ForeignKey('auth.User') title = models.CharField(max_length=200) text = models.TextField() created_date = models.DateTimeField( default=timezone.now) published_date = models.DateTimeField( blank=True, null=True) def publish(self): self.published_date = timezone.now() self.save() def __str__(self): return self.title
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
14 / 71
Modèle exemple
>> myvenv/bin/python3 manage.py makemigrations monblog
>> myvenv/bin/python3 manage.py migrate monblog
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
15 / 71
QuerySet
>> myvenv/bin/python3 manage.py shell>> from monblog.models import Post>> from django.contrib.auth.models import User>> User.objects.all()>> User.objects.create(username='olivier')>> User.objects.all()>> User.objects.get(username='olivier')>> moi = User.objects.get(username='olivier')>> Post.objects.create( author = moi, title = 'Mon titre', text = 'Test')>> Post.objects.filter(author=moi)
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
16 / 71
QuerySet
>> post = Post.objects.get(id=1)
>> post.publish()
>> Post.objects.filter(published_date__isnull=False)
>> Post.objects.order_by('created_date')
>> Post.objects.order_by('-created_date')
>> exit
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
17 / 71
Administration
Créer un superadmin :myvenv/bin/python3 manage.py createsuperuser
Mettre dans monblog/admin.py :from django.contrib import adminfrom .models import Postadmin.site.register(Post)
Relancer le serveurmyvenv/bin/python3 manage.py runserver
Aller sur : http://127.0.0.1:8000/admin/
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
18 / 71Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
19 / 71
Urls
Ajouter l'URL dans monprojet/urls.py :urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'', include('monblog.urls')),]
Créer le fichier en conséquence : monblog/urls.pyfrom django.conf.urls import patterns, include, urlfrom . import viewsurlpatterns = patterns('', url(r'^$', views.post_list),
)
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
20 / 71
Templating
Ajouter l'URL dans monblog/views.py :from django.shortcuts import renderdef post_list(request): return render(request, 'blog/post_list.html', {})
Créer les dossiers puis le fichier en conséquence :>>> mkdir monblog/templates>>> mkdir monblog/templates/blog>>> vim monblog/templates/blog/post_list.html
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
21 / 71
Comparaison Python / Php
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
22 / 71
Comparaison Python / Php
Olivier Pons / 2016
Symfony : générer l'interface d'administration / Sonata- Installer le bundle- Rajouter / modifier le routing- Publier les assets- Décommenter le traducteur (multilangue)- Supprimer les routes inutiles- Générer toutes les classes d'admin.- Eventuellement, activer cmf_tree (→ 3 actions en plus)http://symfony.com/doc/current/cmf/tutorial/sonata-admin.html
Django : rien à faire. Si, si. Rien.
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
23 / 71
Templates / Données dynamiques
Lancer python ”local” : myvenv/bin/python3Puis
import osos.environ['DJANGO_SETTINGS_MODULE']='monprojet.settings'from django.contrib.auth.models import User
import monblog.modelsposts = monblog.models.Post.objects\ .filter(published_date__isnull=False)\ .order_by('published_date')posts
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
24 / 71
Templates / Données dynamiques
Toutes les conditions possibles sont après ”__” :
xxx.filter(nomchamp__lte = xx)xxx.filter(nomchamp__gt = xx)xxx.filter(nomchamp__startwith = xx)xxx.filter(nomchamp__endswith = xx)xxx.filter(nomchamp__exact = xx)xxx.filter(nomchamp__iexact = xx)xxx.filter(nomchamp__contains = xx)xxx.get(id = xx)xxx.objects.all()[:5]
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
25 / 71
Templates / Données dynamiques
Ajouter dans monblog/views.py :
from django.shortcuts import renderfrom .models import Postdef post_list(request): posts = Post.objects\ .filter(published_date__isnull=False)\ .order_by('published_date') return render( request, 'blog/post_list.html', {'posts': posts} )
Relancer le serveur WebOlivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
26 / 71
Templates / Données dynamiques
Ajouter dans monblog/templates/blog/post_list.html :
{% for post in posts %}<div> <p>Publié le : {{ post.published_date }}</p> <h1><a href="">{{ post.title }}</a></h1> <p>{{ post.text|linebreaks }}</p></div>{% endfor %}
Relancer le serveur Web
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
27 / 71
Templates / Données statiques
Créez le dossier ”static” à la racine puis ”css” :mkdir staticmkdir static/css
Modifiez ”monprojet/settings.py” :STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"),)
Relancer le serveur Web
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
28 / 71
Templates / Données statiques
Modifier première ligne de”monblog/templates/blog/post_list.html” :{% load staticfiles %}
Puis dans le <head></head> ajouter :
<link rel="stylesheet" href="{% static "css/blog.css" %}">
Relancer le serveur Web
→ Intégrer totalement un boilerplate au choix (voir après)
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
29 / 71
Boilerplates
Initializr http://www.initializr.com/99lime http://www.99lime.com/elements/Alsacreation http://schnaps.it/http://fortawesome.github.io/Font-Awesome/cheatsheet/
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
30 / 71
Templates / Héritage
Fichier base.html contient toute la baseavec des blocs vides :{% block content %}{% endblock %}
Les fichiers qui héritent ”remplissent” ces blocs :”monblog/templates/blog/post_list.html” :{% block content %} {% for post in posts %} … {% endfor %}{% endblock content %}
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
31 / 71
Url + Template + QuerySet
Editer monblog/urls.py y ajouter dans les patterns :url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
Editer ”monblog/views.py” :from django.shortcuts import render, get_object_or_404
def post_detail(request, pk): post = get_object_or_404(post, pk=pk) return render( request, 'blog/post_detail.html', {'post': post} )Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
32 / 71
Url + Template + QuerySet
Editer ”monblog/templates/blog/post_detail.html” :
{% extends "blog/base.html" %}{% block content %} <div class="date"> {% if post.published_date %} Publié le : {{ post.published_date }} {% endif %} </div> <h1>{{ post.title }}</h1> <p>{{ post.text|linebreaks }}</p>{% endblock %}
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
33 / 71
Formulaires – Simples (pas liés à un modèle)
Principe
→ Déclarer une classe dérivéede ”forms.Form” dans forms.py
→ Déclarer une vue de type ”FormView”dans views.py
→ Mettre la forme en visuel dansles templates (xxx.html)
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
34 / 71
Formulaires – Simples (pas liés à un modèle)
forms.py
class RegisterForm(forms.Form): username = forms.CharField() prenom = forms.CharField() etc. prenom = forms.CharField( label=u'Entrez votre prénom', max_length=100)
Ce ne sont que des définitions de champs = ”Fields”
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
35 / 71
Formulaires – Simples (pas liés à un modèle)views.py
class RegisterView(FormView): template_name = 'applancement/index.html' form_class = RegisterForm def form_valid(self, form): username = form.cleaned_data['username'] prenom = form.cleaned_data['prenom'] ... return HttpResponseRedirect(u'{0}{1}'.format( site_web, self.request.META['PATH_INFO'] ))
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
36 / 71
Formulaires – Simples (pas liés à un modèle)
templates/index.html
<form action="{% url 'register' %}" method="post"> {% csrf_token %} {% for field in form %} {{ field.label_tag }}<br />{{ field }}<br /> {% if field.errors %} {{ field.errors }} {% endif %} {{ field.help_text }} {% endfor %} {{ form.non_field_errors }} <input type="submit" value="Register!"></form>
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
37 / 71
Formulaires
Editer ”monblog/forms.py” :
from django import formsfrom .models import Post
class PostForm(forms.ModelForm):
class Meta: model = Post fields = ('title', 'text',)
← formulaires Django← notre modèle
← Classe dérivée
← classe où définir : ← - la table ← - les champs
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
38 / 71
Formulaires
Ajouter le lien vers le formulaire :
<a href="{% url "blog.views.post_new" %}" class="top-menu"> <span class="glyphicon glyphicon-plus"></span></a>
Olivier Pons / 2016
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
39 / 71
Droits
Authentification
Autorisation
Installation
Olivier Pons / 2016
Vérifie que l’utilisateurest bien celui qu’il prétend être
Détermine ce qu’un utilisateurauthentifié est autorisé à faire
Tout est déjà fait (settings.py)
django.contrib.authAuthentification
django.contrib.contenttypesAssociation modèles ↔ permissions
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
40 / 71
Décorateurs
Olivier Pons / 2016
from django.views.decorators.http import require_http_methods
@require_http_methods(["GET", "POST"])def my_view(request): # arrivé ici = que GET ou POST ! pass→ require_GET(), require_POST(), require_safe()
from django.contrib.auth.decorators import login_required
@login_required(login_url='/login/')def my_view(request): ...
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
41 / 71
Décorateurs
Olivier Pons / 2016
from django.contrib.auth.decorators import permission_required
@permission_required('polls.can_vote', login_url='/login/')def my_view(request): ...
Dans l'application polls :
class Poll(models.Model):
def can_vote(self, user): return not self.vote_set.filter(user=user).exists()
Technologies avancées
1 – Django – Blog
2 – Site basique2 – Site basique
42 / 71
Décorateurs
Olivier Pons / 2016
from django.contrib.auth.decorators import user_passes_test
def email_ok(user): return user.email.endswith('@gmail.com')
@user_passes_test(email_ok)def my_view(request): ...
Technologies avancées
2 – Django – Suppléments
2 – Site basique2 – Site basique
43 / 71
URLs paramétrées
Olivier Pons / 2016
Dans urls.py
urlpatterns = [....url(_(r'^vente-groupee/(?P<slug>[a-zA-Z0-9-_]+)/$'), p_views.DetailView.as_view(), name='vente_groupee'),....
Dans un fichier de template :
<a href="{% url 'vente_groupee' monparam %}">Ici<a/>
Technologies avancées
2 – Django – Suppléments
2 – Site basique2 – Site basique
44 / 71
Sessions
Olivier Pons / 2016
Dans settings.py vérifier que MIDDLEWARE_CLASSES contientdjango.contrib.sessions.middleware.SessionMiddlewarer
Puis dans les vues :→ Le premier paramètre d'une vue est un objet HttpRequest→ Via cet objet, on accède à la propriété sessionrequestion.session.['id']=654654exemple = requestion.session.get('id')del request.session['id']
Fonctions les plus utilisées de session :keys(), items(), setdefault(), clear(), flush()
https://docs.djangoproject.com/fr/1.8/topics/http/sessions/
Technologies avancées
2 – Django – Suppléments
2 – Site basique2 – Site basique
45 / 71
Namespace
Olivier Pons / 2016
Définition du namespace dans la route ”principale”
Ajouter dans urls.py
urlpatterns = [ url(_(r'^monapp/'), include('monapp.urls', namespace="produits")), url(r'^admin/', include(admin.site.urls)),]
Technologies avancées
2 – Site basique2 – Site basique
46 / 71
Namespace
Olivier Pons / 2016
Définition des routes dans l'application même : blog/urls.py
from django.conf.urls import include, urlfrom django.contrib import adminfrom . import views
urlpatterns = [ url(r'^$', views.IndexView.as_view(), name='index'),]
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
47 / 71
Modèles : choix multiple
Olivier Pons / 2016
from django.db import modelsfrom django.utils.translation import gettext_lazy as _
DIFFICULTY = (('easy', _('Easy')), ('medium', _('Medium')), ('hard', _('Hard')))class Exercise(models.Model):
name = models.CharField(max_length=300, unique=True) level = models.CharField( max_length=15, choices=DIFFICULTY)
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
48 / 71
Modèles : base abstraite
Olivier Pons / 2016
class BaseModel(models.Model):
date_creation = models.DateTimeField( auto_now_add=True )
date_last_modif = models.DateTimeField( auto_now=True )
class Meta: abstract = True
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
49 / 71
Modèles : exemple de filtre
Olivier Pons / 2016
https://docs.djangoproject.com/fr/1.8/topics/db/queries/
2 – Django – Suppléments
Dans le modèle :class Produit(BaseModel): tags = models.ManyToManyField( Tag, related_name='produits' )
Dans la vue :Tag.objects.filter( produits__in=Produit.objects.all()).distinct()
Technologies avancées
2 – Site basique2 – Site basique
50 / 71
Administration : ManyToMany
Olivier Pons / 2016
class ProduitTagsInline(admin.TabularInline):
model = Produit.tags.through extra = 0
class ProduitDescriptionsInline(admin.TabularInline):
model = Produit.descriptions.through extra = 0
class ProduitAdmin(admin.ModelAdmin):
inlines = [ProduitTagsInline, ProduitDescriptionsInline] exclude = ('descriptions', 'tags')
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
51 / 71
Administration : ManyToMany
Olivier Pons / 2016
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
52 / 71
Administration : même clé étrangère
Olivier Pons / 2016
→ models.pyclass LangueTraduction(BaseModel): src = models.ForeignKey('Langue', related_name='langue_src') dst = models.ForeignKey('Langue', related_name='langue_dst') nom = models.CharField(max_length=50)
→ admin.pyclass LangueTraductionsInline(admin.TabularInline): # ! fk_name = obligatoire sinon pas visible : fk_name = 'src' model = LangueTraduction extra = 0
class LangueAdmin(admin.ModelAdmin): inlines = [LangueTraductionsInline]
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
53 / 71Olivier Pons / 2016
2 – Django – Suppléments
Administration : même clé étrangère
Technologies avancées
2 – Site basique2 – Site basique
54 / 71
Traduction
Olivier Pons / 2016
Au moment où la fonction est appeléefrom django.utils.translation import ugettext as _
Au moment où la chaîne est réellement utiliséefrom django.utils.translation import ugettext_lazy as _
Créer un dosser ”locale” dans le projet
Avec manage.py shell :makemessages -l frmakemessages -l encompilemessages
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
55 / 71
Traduction
Olivier Pons / 2016
Pour qu'il charge ces chaines :Dans settings.py, ajouter :
LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale'),)
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
56 / 71
Champs de type ImageField
Olivier Pons / 2016
Répertoire des fichiers ”téléversés” :
Dans settings.py, ajouter :MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
Puis dans urls.py, ajouter :urlpatterns = [ ... url(r'^public/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),]
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
57 / 71
Lancer des commandes SQL en direct
Olivier Pons / 2016
Exemple ici pour simuler le ”DESC [table]” de mysql :Lancer python en ligne de commande
from django.db import connection
cursor = connection.cursor()cursor.execute("PRAGMA table_info(ventegroupee)")for row in cursor: print(row)
Pour la note : cursor est une classe ”iterable”,donc on peut faire un ”for” dessus
2 – Django – Suppléments
Technologies avancées
2 – Site basique2 – Site basique
58 / 71
Outils Django déjà en production
Olivier Pons / 2016
Allez ici :
https://github.com/divio/django-cms
Installez le en suivant les instructions.
2 – Django – Suppléments
Technologies avancées
3 – Django – Jeu de rôle
2 – Site basique2 – Site basique
59 / 71
Modèle exemple
Autre exemple models.py :
from django.db import modelsfrom django.utils import timezonefrom django.utils.translation import ugettext_lazy as _
class CharacterClass(models.Model): name = models.CharField(_(u'Nom de la Classe'),max_length=80) playable = models.BooleanField(_(u'Le joueur peut le choisir')) def __str__(self): return self.name
Olivier Pons / 2016
Technologies avancées
3 – Django – Jeu de rôle
2 – Site basique2 – Site basique
60 / 71
Modèle exemple
Types existants :
CharFieldBooleanFieldEmailFieldPositiveIntegerFieldTextFieldForeignKeyOneToOneFieldManyToManyField
Olivier Pons / 2016
Technologies avancées
3 – Django – Jeu de rôle
2 – Site basique2 – Site basique
61 / 71
Modèle exemple
class CharacterManager(models.Manager): def get_query_set(self): return super(CharacterManager, self)\ .get_query_set()\ .filter(playable = True)
class CharacterClass(models.Model): ... objects = models.Manager() # Manager par défaut playable_character = CharacterManager() # Playable Manager
playable = CharacterClass.objects.filter(Playable = True)playable = CharacterClass.playable_character.all()
Olivier Pons / 2016
Technologies avancées
3 – Django – Jeu de rôle
2 – Site basique2 – Site basique
62 / 71
Vues génériques
monblog/urls.py
→ on peut y ajouter directement :
from django.conf.urls import urlfrom django.views.generic import TemplateViewurlpatterns = [ url(r'^apropos/$', TemplateView.as_view( template_name='apropos.html' ))]
Olivier Pons / 2016
Technologies avancées
3 – Django – Jeu de rôle
2 – Site basique2 – Site basique
63 / 71
Vues génériques : dérivation# monapp/views.pyfrom django.views.generic import TemplateView
class AproposView(TemplateView): template_name = "apropos.html"
# urls.pyfrom django.conf.urls import urlfrom monapp.views import AproposView
urlpatterns = [ url(r'^apropos/', AproposView.as_view()),]
Olivier Pons / 2016
Technologies avancées
3 – Django – Jeu de rôle
2 – Site basique2 – Site basique
64 / 71
Vues génériques : listes
class IndexView(generic.ListView):
template_name = 'produits/index.html' context_object_name = 'liste_produits'
def get_queryset(self): """ Dites ce que cela renvoie : """ return Produit.objects.order_by( '-date_v_fin', '-date_v_debut' )[:5]
Olivier Pons / 2016
Technologies avancées
3 – Django – Jeu de rôle
2 – Site basique2 – Site basique
65 / 71
Vues génériques : détail
from django.views.generic.detail import DetailViewfrom django.utils import timezonefrom .models import Produit
class MaDetailView(DetailView): template_name = 'produits/detail.html' model = Produit def get_context_data(self, **kwargs): context = super(MaDetailView, self) .get_context_data(**kwargs) context['now'] = timezone.now() return context
Olivier Pons / 2016
Technologies avancées
3 – Django – Sujet à faire
2 – Site basique2 – Site basique
66 / 71
Choisissez un site à faire parmi les suivants
Réservation de places de concertMédiathèqueBlog multi-utilisateurs multi rôlesVente de services (développement, formation)Rencontre entre professionnels (”à la LinkedIn”)SAAS de comptabilité basiqueCréation communautaire de livresPrésentation et statistiques détaillées d'un MMORPGCrowdfunding (”à la kickstarter / indiegogo”)Site d'apprentissage en ligneRéservation de tables d'un restaurant
Olivier Pons / 2016
Technologies avancées
4 – Structure classique
2 – Site basique2 – Site basique
67 / 71
Varnish
Configuration de varnish : /etc/varnish/default.vcl :
backend apache { .host = "127.0.0.1"; .port = "8080";}
backend nodejs { .host = "127.0.0.1"; .port = "3000";}...
Olivier Pons / 2016
Technologies avancées
4 – Structure classique
2 – Site basique2 – Site basique
68 / 71
Varnish...sub vcl_recv { if (req.url ~ "(?i)\.(jpeg|jpg|...|html|htm)$") { unset req.http.Cookie; } if ( (req.http.host ~ "olivierpons\.(.*)") || (req.http.host ~ "krystallopolis\.(.*)") ) { set req.backend_hint = apache; set req.http.X-Server = req.http.host; } ...
Olivier Pons / 2016
Technologies avancées
4 – Structure classique
2 – Site basique2 – Site basique
69 / 71
Varnish
... # Surcharge pour NodeJS if ( (req.http.host ~ "node\.wogwog\.(.*)") ) { set req.backend_hint = nodejs; set req.http.X-Server = req.http.host; # "pass" = passer direct sans cache possible return(pass); }}...
Olivier Pons / 2016
Technologies avancées
4 – Structure classique
2 – Site basique2 – Site basique
70 / 71
Varnish
...sub vcl_deliver { set resp.http.Server = "WTF Server"; # Supprimer toutes les signatures : unset resp.http.Via; unset resp.http.X-Powered-By; unset resp.http.X-Varnish;}
Olivier Pons / 2016
Technologies avancées
4 – Structure classique
2 – Site basique2 – Site basique
71 / 71
Apache / NodeJS / Python
Apachehttpd.confListen 8080
NodeJSbin/wwwvar port = normalizePort(process.env.PORT || '3000');
Python / Djangopython manage.py runserver 8080
Olivier Pons / 2016