## page was renamed from Ateliers/Django/Frontend = Django : Frontend : interfaces publiques d'un site = <> ---- == INTRODUCTION == * Objectifs * présenter des données dans le frontend (interface publique) avec Django * Documentation * doc : bonne version de django * officielle : [[https://docs.djangoproject.com/en/1.4/|Django 1.4]], [[https://docs.djangoproject.com/en/1.1/|Django 1.1]] * français : http://docs.django-fr.org/ * tutoriel * Part 1 : créer un projet, créer une app, jouer avec ORM (API) '''couvert ici''' * Part 2 : backend (admin) ''pas couvert ici (voir atelier [[Ateliers/Django/Backend|Backend]])'' * Part 3 : frontend '''couvert ici, plus directement même ;)''' * Part 4 : forms et vues génériques ''pas couvert ici'' * Environnement technique * Python >= 2.5 * Django 1.1.1 ou 1.4 * South 0.6 ou 0.7.4 (optionnel, recommandé) * Vérification des versions : {{{ >>> import django >>> django.get_version() '1.4' >>> import south >>> south.__version__ '0.7.4.' }}} * Django : version recommandée à l'AUF * la version qui vient avec debian sur les serveurs de production * sauf si vous êtes prêt à assurer une maintenance manuelle de Django ---- == PARTIE 1 : RAPPELS ET AMORCE DU PROJET == === Rappels === ''Ces rappels couvrent les parties 1 et 2 de l'[[Ateliers/Django/Backend/Support|atelier Backend]]'' * Développement web : schéma sur le [[http://montrealpython.org/r/attachments/13/web-development.jpg|développement web]] * Django : les principaux fichiers dans l'architecture d'un projet * Projet carto : définition du besoin et modélisation === Amorce du projet === 1. Prendre ces sources avec jeu de données ('''recommandé'''): ''superuser = admin/admin'' * Projet carto : Django 1.4 * Projet carto : [[Ateliers/Django/Frontend/Support?action=AttachFile&do=get&target=carto_1_1_backend_final.tar.gz|Django 1.1.1]] 1. ou repartir de votre code du projet carto de l'[[Ateliers/Django/Backend/Support|atelier Backend]] si vous l'avez suivi avant 1. ou partir à zéro en codant le projet : {{{ django-admin.py startproject carto }}} Django 1.1.1 : {{{ django-admin startproject carto }}} {{{ cd carto python manage.py startapp annuaire }}} * coder les modèles de l'app annuaire : annuaire/models.py : {{{ from django.db import models class Etablissement(models.Model): nom = models.CharField(max_length=255) sigle = models.CharField(max_length=50) def __unicode__(self): return self.nom class Personne(models.Model): nom = models.CharField(max_length=255) prenom = models.CharField(max_length=255, blank=True, null=True) date_naissance = models.DateField(blank=True, null=True) universite = models.ForeignKey('Etablissement', blank=True, null=True) def __unicode__(self): return "%s %s" % (self.nom.upper(), self.prenom) }}} * activer l'admin dans urls.py : {{{ # ... from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # ... url(r'^admin/', include(admin.site.urls)), ) }}} * associer les modèles de l'app annuaire à l'admin : créer annuaire/admin.py : {{{ from django.contrib import admin from annuaire.models import * admin.site.register(Etablissement) admin.site.register(Personne) }}} * configurer le projet dans settings.py : {{{ DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 'NAME': 'carto.db', # Or path to database file if using sqlite3. # ... } } INSTALLED_APPS = ( # ... 'annuaire', 'django.contrib.admin', # ... ) }}} * créer les tables dans la DB {{{ python manage.py syncdb }}} * saisir un jeu de données dans l'admin : http://127.0.0.1:8000 ---- == PARTIE 2 : FRONTEND (INTERFACES PUBLIQUES) == === Frontend : présenter les données dans les interfaces publiques === ==== Frontend vs Backend ==== * public/privé : présentation données au public / gestion en privée * métaphore de boutique/entrepôt ou * métaphore de restaurant/cuisine ==== Flux d'info de requête à réponse ==== * urls.py https://docs.djangoproject.com/en/1.4/topics/http/urls/ {{{ urlpatterns = patterns('', url(r'^$', 'carto.views.home', name='home'), # ... ) }}} * views.py https://docs.djangoproject.com/en/1.4/topics/http/views/ ''voir tutoriel Part 3 (version shortcut)'' https://docs.djangoproject.com/en/1.4/intro/tutorial03/ Django 1.4 (>= 1.3) {{{ from django.shortcuts import render def home(request): c = { } return render(request, 'home.html', c) }}} Django 1.1.1 (<= 1.3) {{{ from django.shortcuts import render_to_response from django.template import Context, RequestContext def home(request): c = {} return render_to_response("home.html", Context(c), context_instance = RequestContext(request)) }}} * templates https://docs.djangoproject.com/en/1.4/topics/templates/ * créer répertoire templates Django 1.4 {{{carto/carto/templates/}}} Django 1.1.1 {{{carto/templates/}}} * settings.py {{{ import os # ... TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__), "templates"), ) }}} * templates/home.html ==== Utilisation de variables ==== * views.py ''passer une variable au template'' * templates/home.html ''utiliser une variable :'' {{{ {{ var }} }}} ==== ORM : exploration interactive ==== * views.py ''endroit où on code la logique en Python...'' ''...plus simple si explore interactivement'' {{{ python manage.py shell }}} * ORM (API) : object relationnal mapping https://docs.djangoproject.com/en/1.4//topics/db/queries/ {{{ from annuaire.models import * etablissements = Etablissement.objects.all() for e in etablissements: print e e = etablissements[0] e.personne_set.all() p = Personne.objects.get(id=1) p.id p = Personne.objects.get(id=314) p.id personnes = Personne.objects.filter(universite__nom__contains='Montréal') }}} * annuaire/models.py {{{ related_name = "personnes" }}} * relancer shell {{{ e.personnes.all() e.personnes.count() }}} ==== ORM : utilisation réelle ==== * views.py ''passer les variables pertinentes pour accueil'' * templates/home.html ''boucle for dans template :'' {{{ {% for e in etablissements %} {% endfor %} }}} ==== Héritage de templates ==== * base.html {{{ {% block main %} {% endblock %} }}} * templates {{{ {% extends "base.html" %} {% block main %} }}} ==== URL avec paramètres ==== * pages de détail : capter l'id de l'objet * urls.py : import des urls de l'app annuaire * annuaire/urls.py {{{ urlpatterns = patterns('', # ... url(r'^', include('carto.annuaire.urls')), ) }}} * annuaire/views.py Django 1.4 {{{ from django.shortcuts import render from annuaire.models import Etablissement def etablissement_detail(request, id): etablissement = Etablissement.objects.get(id=id) c = { 'etablissement': etablissement, } return render(request, "annuaire/etablissement_detail.html", c) }}} Django 1.1.1 {{{ from django.shortcuts import render_to_response from django.template import Context, RequestContext from annuaire.models import Etablissement def etablissement_detail(request, id): etablissement = Etablissement.objects.get(id=id) c = { 'etablissement': etablissement, } return render_to_response("annuaire/etablissement_detail.html", Context(c), context_instance = RequestContext(request)) }}} * annuaire/templates/annuaire/etablissement_detail.html {{{ {{ etablissement }} }}} === Frontend pimpé === Télécharger les sources finales du projet pimpé : * sources finales Django 1.4 * [[https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support?action=AttachFile&do=get&target=carto_1_1_final.tar.gz|sources finales Django 1.1.1]] * superuser dans la DB de ces sources : * username : admin * password : admin * pour créer un autre superuser (le vôtre) : {{{ python manage.py createsuperuser }}} Pimpé? Quoi de neuf? ==== Fichiers statiques : CSS, images et js ==== https://docs.djangoproject.com/en/1.4/howto/static-files/ * répertoire : static * css * images * js * settings.py {{{ MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'media') MEDIA_URL = '/media/' STATIC_ROOT = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'sitestatic') STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(os.path.dirname(__file__), "static"), ) }}} * urls.py {{{ from django.contrib.staticfiles.urls import staticfiles_urlpatterns urlpatterns += staticfiles_urlpatterns() }}} ==== Connexion du user ==== * templates * connexion.html * deconnexion.html * urls.py * connexion * deconnexion * settings.py {{{ LOGIN_REDIRECT_URL = "/" }}} == EXERCICE == === Ajouter application Formation === ''Créer l'application formation pour le projet répertoire'' === Ajouter modèle Formation === * Formation * nom * date_debut * date_fin * etablissement === Durée d'une Formation === * Formation.duree() {{{ """Durée prévue en fonction des dates de début et de fin""" }}} == CONCLUSION : POUR CONTINUER == * Autres aspects non couverts (quelques uns) * permissions et décorateurs * manage.py inspectdb * manage.py test * forms * generic views * templates : tags, filtres * Mailing list Django users : http://groups.google.com/group/django-users * Channel IRC #django : irc://irc.freenode.net/django * Contribs, plugins https://docs.djangoproject.com/en/dev/ref/contrib/ * south * reversion * Autre : pypi http://pypi.python.org/ * Savourez!