PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

Garder une video flash en full screen et travailler sur un autre écran

mardi 6 août 2013 à 13:59

Vous avez deux écrans. Vous regardez un tuto video sur le premier, et vous testez le code sur le deuxième. Malheureusement, impossible de mettre la vidéo en plein écran, car à peine avez vous cliqué sur le deuxième, que la vidéo retourne en mode réduit.

Il existe un hack pour pallier ce problème.

J’ai bien dis un hack. Un truc moche, dont les conséquences sont mal connues. Mais ça marche, c’est bien pratique, et je suis d’ailleurs en train de rédiger cet article avec le premier épisode de Vikings en fond.

D’abord, il faut chopper un éditeur héxadécimal.

N’importe lequel fera l’affaire, moi sous Ubuntu j’utilise Ghex :

sudo apt-get install ghex

Il va vous falloir ouvrir le binaire flash avec. Yes, à l’ancienne.

La position du binaire est différent pour chaque OS. Je ne sais pas où il est sous Windows (ça doit être une DLL planquée dans system32 ou un truc du genre), mais sous Ubuntu (et surement sous n’importe quel Unix comme Red hat ou Max), on trouve le fichier facilement :

$ locate libflashplayer.so
/usr/lib/flashplugin-installer/libflashplayer.so

Du coup, on édite le fichier avec l’éditeur hexa en mode admin :

$ sudo ghex /usr/lib/flashplugin-installer/libflashplayer.so

Il faut ensuite recherche la chaîne _NET_ACTIVE_WINDOW.

Pour ghex, c’est dans, le menu recherche est dans Édition > Rechercher :

Capture d'écran de la fenêtre de recherche du logiciel ghex

Attention, ne faites pas de copier / coller. Tapez la chaîne à la main.

Dans ce logiciel, la recherche sous forme de texte se fait dans la partie droite de la fenêtre.

L’éditeur va surligner le terme de la recherche, et va falloir cliquer sur n’importe quelle lettre et la remplacer par une autre.

Capture d'écran de la fenêtre principale du logiciel ghex

Pareil, tout se passe dans la partie droite de la fenêtre

Oui, oui, techniquement on est en train de créer un bug en détruisant le nom d’une constante.

Pour faire le remplacement sous Ghex, pas besoin de faire un backspace, un suprr, ou quoi que ce soit : cliquez sur une lettre de la sélection, appuyez sur une lettre de votre clavier, et c’est bon.

Attention : il va falloir maintenant sauver votre travail, ce qui va faire planter toute app ou video flash en cours.

C’est tout, vous pouvez retournez sur Youtube.

flattr this!

Planescape Torment et Fallout 1, version moderne

lundi 5 août 2013 à 09:17

En attendant Tides of Numenera, le fantastique site Web GOG fournit pour de faibles sommes des heures de plaisir sur Theme Hostpital, Baldur’s Gate ou Heroes Of Might and Magic 3 avec un installeur No CD légal qui fonctionne sur un OS moderne.

Oui mais voilà, si vous voulez rejouer à des monuments comme Planescape Torment ou Fallout 1 sur votre écran 16/9, vous allez très vite ressentir un fort picotement rectal. En effet, ces jeux sont prévus pour des résolutions très basses. Déjà que ces oldies sont tellement pixélisés que la plupart des dialogues ressemblent à “bonjour carré, moi c’est triangle”, mais en 1920×1080, ça fait carrément Picasso période albinos.

Heureusement, il y a des fans qui ont travaillés gratuitement avec acharnement à moder ces jeux aux cours des années, avec des résultats épatant (ceux qui ont joué à l’original comprendront mieux que les amateurs de COD, évidement). Plus que ça, l’ergonomie a largement été améliorée, avec du stacking d’objets, des quêtes restaurées, des bugs corrigés, etc. C’est beau.

On trouve des tutos pour Planescape Torment et Fallout 1 un peu partout.

Sur ce, je vais aller boire un Nuke Cola.

flattr this!

Question d’un lecteur sur le cache et Django

dimanche 4 août 2013 à 08:12

Encore un message du formulaire de contact auquel je n’arrive pas à répondre (delivery failure).

> Subject: Idée d’article/Question
>
> Message Body:
> Salut !
>
> Merci pour vos articles décalés et ceux qui sont plus au centre.
>
> J’ai une petite question sur Django :
> Est-ce possible de mettre toutes les résultats de requetes de l’ORM de
Django dans memcached, et de les récupérer / mettre à jour / supprimer ?
> Pour moi ça bloque au niveau de la mise à jour / suppression.
>
> Du coup je me suis dit que vous pourriez faire un article sur les
différentes méthodes de mise en cache dans Django et ce que on peut
faire avec.

Hello,

Oui, c’est possible.

La mise à jour et la suppression du cache a toujours été une des choses
les plus difficiles en programmation, donc c’est naturel de bloquer dessus.

Pour commencer, utilise django-cache-machine ou johnny-cache, qui sont des
surcouche à l’ORM Django avec cache automatique. Ensuite, tu apprendras
à faire le reste à la main petit à petit.

Pour les pages complètes, des solutions qui n’ont rien à avoir avec
Django, telles que Varnish, sont aussi des approches qui permettent de
gagner pas mal en perfs.

Bref, je note ce truc dans la liste des articles à faire.

Sam

flattr this!

Organisation d’une application Django

samedi 3 août 2013 à 09:28

Article long, tradition :

Question qui est arrivée par le formulaire de contact il y a prêt de 2 mois (désolé ^^), et que je m’étais posé é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 grossisent les premiers, suivi de tests.py. tests.py devrait en principe être celui qui grossi 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 :

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 splitter 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 coulé 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 et les préfixant de 'apps', vous pouvez ajouter le chemin au PYTHON PATH dans le fichiers de settings:

import os
import sys
 
PROJECT_DIR = sys.path.append(os.path.dirname(os.path.realpath(__file__)))
APPS_DIR = os.path.realpath(os.path.join(PROJECT_DIR, '..'))
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, postgres, 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 tous 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, postgres, redis qui auront été générés depuis le 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.

flattr this!

AMA reddit

vendredi 2 août 2013 à 10:49

Un lecteur nous a proposé ça par mail :

Bonjour Sam & Max,

Il serait d’utilité publique si vous pouviez faire un AMA reddit sur python et l’industrie du pron !

Je suis sérieux.

Bonne semaine Heckel et Jeckel !

Ça intéresse d’autres personnes ? Si oui, quel interêt de le faire sur reddit plutôt que sur le blog ? Quel est la meilleur période pour le faire ? Quelle est la marche à suivre ? Pourquoi les torrents qui buggent le font toujours à 99% et jamais à 1% ?

flattr this!

Error happened! 0 - count(): Argument #1 ($value) must be of type Countable|array, null given In: /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php:428 http://ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/?140 #0 /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php(999): VroumVroum_Blog->update() #1 /var/www/ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/index.php(1): require_once('...') #2 {main}