Organisation d’une application Django 33


Article long, tradition :

Question qui est arrivée par le formulaire de contact il y a près de 2 mois (désolé ^^), et que je m’étais posée également en commençant avec ce framework.

En effet, Django, c’est du pur Python. On peut structurer son projet comme on veut. On pourrait même tout mettre dans un seul dossier : les vues, les templates, le css. Tout.

Mais ce n’est pas parce que c’est possible qu’il faut le faire, et nous allons donc voir les bonnes pratiques.

WARNING : je vais soigneusement ignorer la question des settings, qui mérite un article à part entière.

Naissance du projet

Quand vous commencez un projet avec startproject et startapp, vous allez avoir une arborescence qui va ressembler ça ceci :

.
├── manage.py
├── mon_app
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── project
    ├── settings.py
    ├── urls.py
    └── wsgi.py

Avec ça, on ne fait pas une app, vous allez donc ajouter des formulaires, de l’admin, des templates, du js, du css…

Pour tout ce qui est fichier statique (JS, CSS, images, flash, zips…), la bonne pratique Django est de mettre tout ce qui concerne l’app dans un dossier nommé static à l’interieur de l’app. Django vient en effet avec tous les outils pour les gérer de cette manière.

Pour l’admin et les formulaires, il est d’usage de les mettre dans des modules admin.py et forms.py respectivement.

Quand au template, la bonne pratique est de les mettre dans un sous dossier de l’app nommé template comme pour les fichiers statiques. MAIS, chaque template doit aussi être dans un sous dossier qui porte le nom de l’app. Cela donne :

nom_de_lapp/templates/nom_de_lapp/template.html

La raison à cela est que cela permet à d’autres app de pourvoir utiliser le même nom de template, ou d’écraser votre template explicitement. Inversement votre app peut dans ses templates écraser les templates d’une autre app en ayant un template avec le chemin :

nom_de_lapp/templates/nom_de_lautre_app/template.html

Donc, même si cela parait redondant, toujours créer un sous-dossier avec le nom de l’app dans le dossier templates. Cela se fait de plus en plus avec le dossier static également, mais c’est moins important dans un premier temps pour vous car vous n’allez pas publier ces apps. Donc, vous pouvez ne pas le faire pour static pour le moment.

Enfin, je vous recommande d’avoir toujours les routes qui concernent votre app dans un fichier urls.py dans le dossier de l’app, qui sera inclus par celui du projet. Cela vous aidera pour la suite.

Votre arbo de base va donc ressembler à ça :

.
├── manage.py
├── mon_app
│   ├── admin.py
│   ├── forms.py
│   ├── __init__.py
│   ├── models.py
│   ├── static
│   │   ├── css
│   │   │   └── style.css
│   │   └── js
│   │       └── behavior.js
│   ├── templates
│   │   └── mon_app
│   │       └── index.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── project
    ├── settings.py
    ├── urls.py
    └── wsgi.py

Croissance du projet

Jusqu’ici votre projet était un petit site avec quelques vues, un formulaire, 3 modèles, et c’est tout. Mais il a grandi, et comme dans toute adolescence, ça commence à être le bordel dans la chambre : le fichier views.py contient 25 fonctions courtes, le fichier models.py 4 classes mais fait 800 lignes.

La première chose à faire à ce niveau, c’est de transformer les modules en packages.

Souvenez-vous : la règle la plus importante avec Django, c’est que c’est juste du Python.

On peut donc prendre chaque fichier de modules, et les diviser en plusieurs sous fichiers (chacun représentant un jeu de fonctionnalités), puis les mettre dans un packages. Pour rappel, un package c’est un dossier avec un fichier __init__.

Exemple, vous avez views.py qui ressemble à ça :

def home():
 
def user_account():
 
def profile():
 
def messages():
 
def forum():
 
def articles():

Vous allez faire un dossier views avec fichier __init__ et 3 modules :

views
├── communication.py <= contient formum() et messages()
├── content.py  <= contient articles() et home()
├── __init__
└── user.py  <= contient user_account() et profile()

A vous de trouver des noms explicites. Prenez le temps de le faire, un bon nom, c'est 10 lignes de documentation en moins.

Maintenant concernant les imports, vous allez devoir faire :

from mon_app.views.content import home

Au lieu de :

from mon_app.views import home

Si cela vous ennuie, il est tout ça fait possible de faire dans __init__.py :

from communcation import *
from content import *
from user import *

Et vous n'aurez pas à changer le moindre de vos imports. Pour Python, un module et un package, c'est pareil.

Si votre app devient grosse, je vous invite quand même a réserver les imports dans __init__ pour les fonctions les plus courantes, afin de ne pas saturer l'auto-completion quand vous êtes dans le shell ou dans votre IDE.

Bref, si vous appliquez cela à tous vos modules un peu gras, ça peut donner :

.
├── manage.py
├── mon_app
│   ├── admin.py
│   ├── forms
│   │   ├── communication.py
│   │   ├── __init__.py
│   │   └── user.py
│   ├── __init__.py
│   ├── models
│   │   ├── content.py
│   │   ├── __init__.py
│   │   ├── stats.py
│   │   └── user.py
│   ├── static
│   │   ├── css
│   │   │   └── style.css
│   │   └── js
│   │       └── behavior.js
│   ├── templates
│   │   └── mon_app
│   │       └── index.html
│   ├── tests.py
│   ├── urls.py
│   └── views
│       ├── communication.py
│       ├── content.py
│       ├── __init__
│       └── user.py
└── project
    ├── settings.py
    ├── urls.py
    └── wsgi.py

Votre app commence vraiment à prendre du poids, mais ça reste manageable. Notez que ceci peut s'appliquer à n'importe quel module qui devient trop gros, y compris admin.py ou urls.py. Généralement ce sont views.py et models.py qui grossissent les premiers, suivi de tests.py. tests.py devrait en principe être celui qui grossit le plus, mais je sais bien que chez la plupart des gens, ce fichier est vide.

Maturité

Tout centraliser au début facilite la tâche. On trouve tout facilement, pas de souci de gestion, ça permet de commencer rapidement. Sur le long terme, le code va s'accumuler et il va devenir difficile de trouver ce que l'on cherche, avoir une image globale de ce qui se passe ou faire des modifications. Mais le pire, c'est pour le partage et la réutilisation de code.

Votre projet est un grand garçon, il est temps de le traiter comme tel.

Cela va passer par la division de votre grosse application monolithique, en plusieurs apps plus petites, chacune représentant une fonctionnalité ou un groupe de fonctionnalités. Au début ce concept de "groupe de fonctionnalités" est difficile à appréhender pour un débutant, alors commencez par faire simple : faites une app par 'partie du site' comme par exemple le dashboard, le forum, le compte utilisateur, etc. On peut faire mieux, mais ce sera déjà bien.

Plus tard, quand vous serez plus à l'aise avec ce principe, vous pourrez étudier la notion de "composants" et de "pluggable apps" qui vous amèneront à faire des applications réutilisables (et même partageables sur le Net) orientées fonctionalités : messaging, comments, anti-spam, registration, user management, etc. Mais cela implique bien d'autres choses qui sont en dehors du cadre de cet article. Pour le moment, concentrez-vous sur la division de votre grosse app en plusieurs plus petites.

Dans notre exemple on note qu'il y a 3 grosses parties : une partie "information", une partie "communication" et une partie "contenu". Nos apps sont donc toutes trouvées.

Il n'est pas rare non plus d'avoir des petits bouts dont on ne sait quoi faire, et aussi des fondations de code qui ne se prêtent pas vraiment à être mis dans une app, comme la home page ou le miniscule modèle stats qui ici n'est pas encore assez gros. Dans ce cas, il suffit de créer une application principale qui va contenir tout ça, en attendant que vous vienne l'inspiration de classifier / factoriser / répartir son contenu ailleurs. J'appelle souvent cette app "core", à défaut d'un meilleur nom.

.
├── communication
│   ├── admin.py
│   ├── forms.py
│   ├── __init__.py
│   ├── templates
│   │   └── communcation
│   │       └── forum.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── content
│   ├── admin.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── core
│   ├── admin.py
│   ├── __init__.py
│   ├── static
│   │   ├── css
│   │   │   └── style.css
│   │   └── js
│   │       └── behavior.js
│   ├── templates
│   │   └── mon_app
│   │       └── index.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── project
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── user
    ├── admin.py
    ├── forms.py
    ├── __init__.py
    ├── models.py
    ├── templates
    │   └── user
    │       └── profile.html
    ├── tests.py
    ├── urls.py
    └── views.py

Vous noterez des phénomènes intéressants :

  • Une app n'a pas forcément besoin de contenir models + urls + templates... Une partie suffisament grosse, indépendante et spécialisée justifie d'être déplacée dans une app.
  • Les packages views et models sont redevenus des fichiers. On pourra les transformer à nouveau en package quand ils grossiront.
  • Il y a des templates qui ont magiquement apparu. La raison à cela, c'est que en écrivant le tuto j'ai oublié de faire suivre le nombre de fichiers statiques et de templates pour qu'ils correspondent aux fonctionnalités et du coup je me retrouve comme un con :-) Alors vous allez faire comme si vous avez rien vu, et comme si ils étaient là depuis le départ, parce que j'ai pas le courage de tout refaire.
  • Il n'y a pas de model dans communication. Ca n'a aucun sens. Même problème que précédemment. C'est un exemple, bordel !
  • static est resté dans core. Ca c'est très courant. Au début vous n'aurez pas de fichiers statiques répartis entre les apps. Avec le temps, ça vient. Mais généralement ça se fait en dernier car ça demande de vraiment bien penser son archi.
  • Chaque app a gagné un fichier urls.py qui doit donc être inclus dans project/urls.py. Il est parfaitement acceptable d'avoir un app qui n'a pas d'urls.py (ou de models.py, ou de forms, ou de presque rien de tout ça). Simplement je pense que ça sera plus facile pour vous de penser dans un premier temps avec des "parties de site" et donc des urls.

Au début, vos apps seront fortement couplées. Avec l'expérience (et peut être un article), vous apprendrez à les rendre de plus en plus autonomes, et finalement à avoir un maximum d'apps génériques et quelques apps glues. Je vous rassure, nos codes en prod à Max et moi sont pleins de couplages également. Il y a la théorie, et le résultat de 200 mises en prod.

Bref, vous allez ensuite faire grossir vos applications organiquement comme on a vu dans Croissance du projet et quand elles dépassent une masse critique (mesurable scientifiquement), vous la splittez en apps plus petites, et ainsi de suite.

L'age de raison

Après de nombreuses mises en production, des tentatives d'automatisation, des fichiers de conf qui vont trainer, des fichiers statiques et des libs ajoutées, vous allez vous apercevoir que même cette archi commence à être brouillonne.

Il est temps de passer en mode pro.

Alors, attention, à partir de la, on tombe dans la guerre de religion : VI VS Emacs, PC VS Mac, Bigoo VS Big Mac, Ulysse VS Télémaque, etc. Bref, le layout d'une application en Django a fait couler beaucoup d'encre et je ne vous propose qu'une des versions possibles.

D'abord, on va regrouper les apps dans un dossier pour éviter d'avoir 20000 dossiers à la racine.

.
├── apps
│   ├── communication
│   │   └── templates
│   │       └── communcation
│   ├── content
│   ├── core
│   │   ├── static
│   │   │   ├── css
│   │   │   └── js
│   │   └── templates
│   │       └── mon_app
│   └── user
│       └── templates
│           └── user
└── project

Afin de toujours permettre d'importer les apps directement et non en les préfixant de 'apps', vous pouvez ajouter le chemin au PYTHON PATH dans le fichiers de settings:

import os
import sys
 
PROJECT_DIR = os.path.dirname(os.path.realpath(__file__))
ROOT_DIR = os.path.dirname(PROJECT_DIR)
APPS_DIR = os.path.realpath(os.path.join(ROOT_DIR, 'apps'))
sys.path.append(APPS_DIR)

Ce n'est pas obligatoire, mais ça facilite beaucoup la vie, et la refactorisation.

Ensuite, il va vous falloir un dossier dans lequel mettre les fichiers de confs (requirements.txt, templates de fichiers de conf nginx, PostGreSQL, Redis, etc) et les scripts de déploiements, et un autre pour la doc. Je le mets en général dans project. Si Max lit jusqu'à cette ligne, il va bien se marrer, vu le bordel qu'il y a dans les arbos de certains de nos projets.

.
├── apps
│   ├── communication
│   │   └── templates
│   │       └── communcation
│   ├── content
│   ├── core
│   │   ├── static
│   │   │   ├── css
│   │   │   └── js
│   │   └── templates
│   │       └── mon_app
│   └── user
│       └── templates
│           └── user
└── project
    ├── deploy
    └── doc

Tous ces fichiers doivent être commités dans un VCS (Git, SVN, mercurial...).

A cela, il faut souvent ajouter une dossier libs qui contient toutes les libs non installables par pip, tous vos forks, vos trucs compilés avec des options zarbs, vos libs persos non Django qui ne sont pas sur pypi, etc. Dans le meilleur des mondes, il vous faut récupérer son contenu dynamiquement avec un script. Dans le meilleur des mondes... Sinon, ajoutez le à votre VCS. Et par simplicité, ajoutez ce dossier au PYTHON PATH.

Ensuite il faut un dossier var, qui va contenir tout ce qui est fichier que le code du projet va manipuler : fichiers statiques collectés par ./manage.py collectstatic, fichiers de log, base de données SQLite, dumps, locks, etc.

Puis il faut un dossier etc dans lequel on va mettre les fichiers de configuration pour le projet, pour ce serveur : le fichiers conf nginx, PostgreSQL, Redis qui auront été générés depuis les templates situés dans project/deploy/. Faites ensuite un lien symbolique depuis ces fichiers dans les dossiers correspondant (par exemple vers /etc/nginx/site-enabled pour un fichier de config nginx).

Ces deux dossiers sont nommés ainsi car c'est la nomenclature des dossiers pour cet usage sous Linux, mais vous pouvez leur donner le nom que vous voulez.

Dans tous les cas, ce sont des dossiers qui ne sont PAS commités dans votre VCS, donc mettez les dans votre blacklist (type .gitignore). Ils sont spécifiques à une installation.

Idéalement il faut les générer avec un truc genre fabric pour pas avoir à le faire à la main, même si vous apprendrez mieux en le faisant à la mano au début. Générer ses fichiers de conf avec des templates, c'est un idéal. Après, il y a vraiment une boîte sur 10 qui le fait dans la pratique.

Puis vous ajoutez un README qui explique rapidement quel dossier contient quoi, où trouver la doc et particulièrement, pointez directement vers la partie de la doc sur l'installation et les dépendances.

.
├── apps
│   ├── communication
│   ├── content
│   ├── core
│   └── user
├── etc
├── libs
├── project
│   ├── deploy
│   └── doc
└── var
└── README.rst

Souvent, je met aussi un symlink du virtualenv à la racine du projet, car c'est très pratique pour jeter un coup d'oeil dans le site-packages.

33 thoughts on “Organisation d’une application Django

  • Sam Post author

    Je constate après relecture que je me suis soucier beaucoup du comment, mais peu du pourquoi. Si il y a des choses qui vous titillent, dites le, je rajouterais les comments nécessaires.

  • foxmask

    fort cool j’en suis passé par les 3 premières étapes :) j’ai encore du chemin à faire mais pour l’heure des applications atomiques conviennent. encore une perle à conserver au chaud.

    merci

  • maethor

    Excellent article, merci beaucoup. Comme tu le dis, c’est souvent difficile quand on débute de s’y retrouver dans la jungle des propositions pour trouver une réponse simple à “comment j’organise un projet putain !?”. D’ailleurs, la question se pose aussi avec les autres framework (flask, bottle…).

    Ta solution est vraiment très élégante. Merci ! :)

    J’ajouterais juste que idéalement, si le VCS est Git, il est possible de gérer les apps sous forme de submodules, pour les publier plus simplement de façon indépendantes, et donc les intégrer plus simplement à d’autres projets.

  • Etienne

    Très utile! J’y reviendrai souvent. Comme le dit maethor, utile aussi pour des framework genre flask ou bottle.

    A vous de trouver des noms explicites. Prenez le temps de le faire, un bon nom, c’est 10 lignes de documentation en moins.

    Aaaarhglh! Pourquoi c’est si difficile à trouver, un nom explicite?

  • Sam Post author

    Parce que classifier les choses se heurtent aux problématiques de taxonomie. On finit par tomber sur des situations imprécises, en double, ou aberrante. Le problème d’un classement, c’est qu’il est toujours arbitraire. Un exemple est “Le Marché céleste des connaissances bénévoles”, livre dans lequel il est écrit que les animaux se divisent en

    a) appartenant à l’Empereur,

    b) embaumés,

    c) apprivoisés,

    d) cochons de lait,

    e) sirènes,

    f) fabuleux,

    g) chiens en liberté,

    h) inclus dans la présente classification,

    i) qui s’agitent comme des fous,

    j) innombrables,

    k) dessinés avec un pinceau très fin en poils de chameau,

    l) et caetera,

    m) qui viennent de casser la cruche,

    n) qui de loin semblent des mouches ».

  • Etienne

    Borges. Foucault en parle dans la préface de “Les Mots et le choses”.

    (ce que nous somme cultivés!)

  • Etienne

    Ça me fait penser aux paradoxes genre: la classe des classes qui ne se contiennent pas est-elle une classe qui se contient ou qui ne se contient pas?

  • Recher

    Eh oui, Dieu donne à Adam le pouvoir de nommer les choses qui l’entourent.

    C’est pas forcément un grand pouvoir, mais ça implique une grande capacité à organiser les choses de manières bordeliques.

    Ah, et sinon ce bout de phrase ne veut rien dire :
    “ou trouver la doc et particulière pointe directement vers la doc d’installation et des dépendances.”

  • Bert

    Tres bon article comme souvent !
    Une seule chose me titille c’est au moment de deplacer les applications dans le sous dossier ‘apps’. Effectivement ca nettoie un peu la racine du projet donc c’est pas mal – meme si ca deplace le probleme un niveau plus bas. Mais surtout ce que j’ai trouve assez etrange c’est l’ajout de ce dossier au PYTHONPATH car l’ajout est fait de maniere “cachee” et va a l’encontre du principe de clarte de Python puisque les imports n’indiquent pas le dossier ou sont vraiment les applications.

  • Sam Post author

    C’est un coût en effet. Après, je pense qu’il est faible vu qu’un coup d’oeil dans le répertoire apps renseigne sur la question. Et il apporte pas mal de bénéfices. Par exemple, si à un moment tu décide de prendre une app et de la mettre sur pypi et donc de la virer de ton projet, tu peux l’installer avec pip, et tout ton code continuera de marcher sans rien toucher.

  • Laurent

    Très bonne article avec plein de bonnes idées à reprendre. Merci Sam :)

    Il aurait peut-être fallu ajouter un petit paragraphe sur la différence entre un projet et une app dans le monde Django. Souvent on entend parler d’une application Django, alors qu’il sagit d’un projet.

    Perso, pour me simplifier le déploiement, je fais en sorte que mon projet Django puisse être packagé (en ajoutant un setup.py à la racine du VCS). Le projet peut alors se retrouver sur PyPI et ça simplifie la vie des personnes qui souhaitent l’insaller.
    Ok, ça sert surtout pour les projets qui ont vocation à être public. Mais j’ai ça a également sont utilité pour envoyer une nouvelle version du projet à un client : on lui envoie zeprojet-1.69.tar.gz, et il a juste à faire un pip install zeprojet-1.69.tar.gz.

  • Max (un autre Max)

    Juste un petit commentaire pour vous remercier pour cet excellent article, très utile et hyper pertinent (j’ai bien galéré au départ sur django sur l’architecture (et je galère encore))…

    J’aime beaucoup votre côté “progressif” car j’ai voulu tout de suite commencer avec la dernière étape (plein de petites apps “fonctionnellement” transverses”), c’était dur :(.

  • sitle

    lol mettre de l’ordre, c’est foutre le bordel ailleurs de toute façons. Qu’est ce que j’aime vos articles lol.

    Bonne continuation.

  • Sam Post author

    Bientôt un article : “l’anarchisme appliqué à la programmation Python”.

  • Dr. Benton

    Merci pour cet article (et les autres !), c’est une formidable base pour s’initier à Django – et francophone, qui plus est, ce qui ne gâche rien.

    J’ai énormément bossé avec PHP, puis me suis mis à Ruby et Rails, mais à force de lire ce blog on a forcément envie de s’essayer un beau jour à Django :-)
    Pour le moment ça me plaît bien beaucoup – et notamment par la liberté qu’autorise le framework. La rigidité d’outils comme Rails est un super repère pour débuter et mieux s’y retrouver dans des applis existantes, mais ça laisse tout de même parfois l’impression de ne pouvoir sortir des sentiers battus et exprimer sa “créativité” (si tant est qu’on puisse utiliser ce terme pour du code ?).

    A noter que de mon coté, pour faire fonctionner la structure avec “apps/” et “project/” à la racine du projet (structure bien plus compréhensible que celle proposée par défaut, avec les settings et les apps au même niveau ; merci beaucoup pour l’astuce !), sur Django 1.6 j’ai plutôt dû faire ceci :

    APPS_DIR = os.path.realpath(os.path.join(BASE_DIR, 'apps'))
    sys.path.append(APPS_DIR)
  • Lmhaydi

    Très bon article, mm chose pour le site, je m’inspire tjr de vos pretigieux articles! bonne continuation

  • Said

    Je confirme le commentaire de “Dr. Benton” par rapport au fichier de settings.py

    En utilisant l’instruction du post, je me retrouvais avec une erreur : “no module named porno” ! Quelle version de django utilise-tu ?

  • Sam Post author

    En effet il y a une typo. Il faudrait plutot :

    PROJECT_DIR = os.path.dirname(os.path.realpath(__file__))
    ROOT_DIR = os.path.dirname(PROJECT_DIR)
    APPS_DIR = os.path.realpath(os.path.join(ROOT_DIR, 'apps'))
    sys.path.append(APPS_DIR)
  • matthieu

    (disclaimer : je ne suis pas du tout dév. web, j’ai juste besoin de faire quelques interfaces de temps en temps)

    J’utilise globalement l’étape « maturité ». Par contre, c’est le déploiement qui est différent. Je package tout systématiquement (python setup.py sdist), et quand je veux installer, je fais mkvirtualenv monprojet && pip install monprojet .
    Une mise à jour ? pip install monprojet –upgrade

    Et les settings, dans tout ça ? Et bien j’utilise un fichier qui s’appelle… defaults.py.
    Plus exactement, j’ai un fichier defaults.py avec des paramètres fonctionnels de base (je commence par LOCAL_PATH qui correspond au dossier du projet, et je définis dedans mon MEDIA_ROOT, ma base SQLite, mon STATIC_ROOT). Dans mon IDE (PyCharm), je dis que le fichier de settings est ce fichier defaults.py. Fantastique, mon IDE reconnaît correctement tous mes templates et gère bien les aspects Django.

    Et j’ai un fichier settings.py, qui va chercher en parallèle defaults.py et customs=import_module(~/.virtualenvs/monprojet/etc/monprojet/settings.py) .
    Ensuite, une petite boucle sur les variables définies dans defaults.py et je les injecte dans le globals() de settings.py, en les overridant par celles de customs quand elles sont définies (bon, c’est l’idée, en pratique c’est un peu plus subtil vu que je veux pouvoir faire des remplacements genre STATIC_ROOT = “%(LOCAL_PATH)s/static” ).

    Et hop, je customize uniquement les paramètres spécifiques à l’installation dans ~/.virtualenvs/monprojet/etc/monprojet/settings.py (qui ne sera jamais touché quand je fais pip install ).

  • Arnaud Lamy

    Merci pour ce très bon article, l’organisation app / projet devient un peu plus clair. J’ai encore bcp de mal à bien voir l’utilité des apps par rapport à une arbo bien maîtrisé maison.

    Débutant avec ce framewrok, je cherche à développer une application web et j’ai bien envie de faire deux apps, une pour le backend avec une api rest et une autre pour le front end. Je verrai bien si j’ai besoin d’exploser par la suite l’app backend. Comme je disais pour moi faire une apps à part, c’est pratique si je peux la réutiliser ailleurs, sinon autant continuer son arbo en évitant les dossiers ou classes trop lourdes.

    Que pensez vous de cette découpe ?

  • Sam Post author

    Ton arbo originale n’a pas d’importance. L’important est que tu prennes le temps de revenir dessus régulièrement pour la modifier et l’adapter au fur et à mesure que ton projet évolue.

    Au début, il est naturel que tu ne saches pas exactement quelles sont les fonctionalités à isoler sous forme d’app, et donc tu fais des apps pour chaque partie de ton architecture. Plus tard, les groupes fonctionnels apparaitrons plus clairs, et tu voudras sans doute revoir ton organisation.

  • Gui.

    Merci beaucoup pour cet article !

    Connaissant le dev web via des framework PHP (codeIgniter, CakePHP…), j’ai été un peu chamboulé au début avec Django. En tant que bon fainéant de dev, je prône la factorisation: je savais qu’il fallait que je m’organise bien mais j’étais perdu avec cette histoire d’app… Concrètement ton article m’a ouvert les yeux, un point reste néanmoins flou… Pour le moment j’ai une app qui gère les utilisateurs et les groupes (pas d’utilisation des groupes Django, nos specs partent sur un autre principe) et il va y avoir une app métier. Dans ma première app j’ai mis en place Bootstrap & JQuery (car Django pas content voulait pas mappé sur le dir static de la racine). Sera t il possible d’utilisé ces css et js depuis l’autre app ? Dans un premier temps les 2 apps seront très très liées mais bon…

  • Napoleon

    Hey ! Bonjour tout le monde !

    J’ai commencé a me former a l’utilisation du Python et de Django tout récemment. Et parfois certaines questions ‘techniques’ ou d’organisations me désarçonnent complètement.

    Heureusement d’ailleurs que des sites comme celui-ci (mais quand même en particulier celui-ci) me donnent un sacré coup de de main quand cela arrive.

    Cependant ( et c’est peut etre bien de ma faute, je n’ai peut etre pas encore assez chercher), je n’ai pas trouvé réponse a la question que je me posais en arrivant sur cette page.

    Le projet sur lequel je travaille est encore dans une phase “enfant” , malgré cela, je commence a avoir des fonctions dans mes views.py qui ressemble de plus en plus a de gros pavés en accumulant 50 ou 100 lignes de codes par fonction.

    Alors, voila ma question: “D’après vous, quelle est la meilleure facon de remédier a ce problème ? Comment redécouper proprement une fonction contenue dans un views.py ?”

    Bonne soirée a vous ;)

  • Sam Post author

    Cela dépend du contenu de la vue :

    • si c’est de la manipulation de données, tu peux mettre ça dans les models.py
    • si c’est de la validation de données, tu peux mettre ça dans forms.py.
    • si c’est du formatage pre template, tu peux mettre ça dans un template tag.
    • pour le reste, tu mets ça dans un module nommé selon le but de la procedure dans ton app (ou une app spécifique pour ça si tu as beaucoup de code). Tu n’est pas limité aux modules existant dans une app, tu peux et doit créé tes propres modules.
  • Napoleon

    Très bien, j’essaierai de suivre ces sages conseils a l’avenir.

    Merci !

  • Personne

    Il y a une balise mal fermée au niveau de “Ce n’est pas obligatoire, mais ça facilite beaucoup la vie, et la refactorisation.”

    Sinon, très bon article !

  • The_Dr

    Hop, et bien voilà, je me disais bien aussi que ce que je faisais de manière empirique devait être logique :-)

    Maintenant c’est bon je suis convaincu : bordel -> organisation -> factorisation -> … et encore le bordel (rangé) !!!

    Question subsidiaire : je n’ai pas de lib mais plutôt un répertoire bin.

    Dans ce répertoire je mets le code pour :

    1 – des actions que je lance soit avec django pour des mises à jour de données (rafraichissement des données issues de sources externes, qui sont parsées)

    2 – lander les actions périodiquement.

    Est-ce la bonne approche pour “bin” ? Je me demande s’il ne vaudrait pas mieux que je rappatrie une partie des codes dans les apps qui existent … Qu’en pensez-vous ?

    Pour la partie “cron” je pourrais la lancer à partir de django. J’ai l’impression que Celery serait mieux (pas de problème de PATH python, gestion des logs, gestion des erreurs, pas de droits root sur la machine de prod, …). Vous avez un petit commentaire sur le sujet ?

  • Sam Post author

    Pour la 1, je mettrais des commandes django plutôt.

    Pour la 2, l’un ou l’autre se vaut. Perso je préfère celery pour toutes les raisons que tu as indiqués, et du coup il y a un module task.py et non un répertoire bin.

  • The_Dr

    OK, super, je vais donc m’y mettre, ya plus qu’à comme dirait l’autre (et ce coup-ci je coche la case de follow-up !).

    D’ailleurs en parlant de cela, la case “follow-up” serait mieux au niveaux des identifiants, cela éviterait de se dire après “oups” j’ai oublié quelle page c’était :-)

  • Baghrous

    Merci pour ce très bon article, l’organisation app / projet devient un peu plus clair. :)

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.