Django-fr

Forum

#1 26-09-2011 17:26:26

stopher
Membre
Lieu : Lille
Inscription : 26-09-2011
Messages : 11
Site Web

Best Practice

Salut à tous ,

Premier message sur ce forum , et premier projet important utilisant Django .

Ma question est simple , selon vous , quelles sont les erreurs récurrentes de débutant sous django à éviter ?

Que ce soit au niveau sécurité, structure des modules, x, y, z, ... smile

Merci d'avance pour vos conseils que j'essayerai d'appliquer à la lettre smile

Ch.

Hors ligne

#2 26-09-2011 17:45:29

Julien Bouquillon
Membre
Inscription : 26-09-2011
Messages : 25

Re : Best Practice

Hello Je dirai :


.se forcer à utiliser les "named urls"

.utiliser la django debug toolbar et bien regarder les requêtes sql générées

.utiliser un vrai serveur http pour les statics

.lire les recos des django "reusable apps" :
http://ericholscher.com/projects/django-conventions/app/

.regarder de bons exemples :
https://github.com/nathanborror/django-basic-apps

.must read :
http://stackoverflow.com/questions/550632/favorite-django-tips-features

my 2 cts


Julien



Le 26 septembre 2011 18:26, Christophe de saint leger
<christophe _AT_ lindev.fr>a écrit :

> Salut à tous ,
>
> Premier message sur ce forum , et premier projet important utilisant
> Django .
>
> Ma question est simple , selon vous , quelles sont les erreurs
> récurrentes de débutant sous django à éviter ?
>
> Que ce soit au niveau sécurité, structure des modules, x, y, z, ... smile
>
> Merci d'avance pour vos conseils que j'essayerai d'appliquer à la lettre
> smile
>
> Ch.
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
>

Hors ligne

#3 26-09-2011 18:06:34

Christophe, Jean-Charles Narbonne
Membre
Inscription : 23-06-2011
Messages : 30

Re : Best Practice

Disclaimer: Je me considère moi même comme débutant.
N'hésitez pas à critiquer chaque point de ma réponse si vous n'êtes pas
d'accord.

Réfléchir à la décomposabilité des projets en privilégient les modules plus
gros que les modules interdépendants.

Si une "interdépendence" est faible, il est parfois pratique de séparer
quand même et de faire un peu de monkey-patch depuis les models du module le
moins générique.

Avoir lu une fois la pep8 ou un résumé. Pour l'intégration de snippet et si
jamais d'autre personnes venaient à joindre le développement.

Utiliser static media et les templates dans les apps.

Reprenez moi si vous pensez que c'est une mauvaise pratique mais pour les
pages complexes, afin de pouvoir gérer les données intelligement en limitant
le nombre de requètes, je fais des itérateurs spécifiquement pour des vues
ou des templates à inclure (genre widget ou lignes de tableau).

Regarder 2/3 fichiers settings de projets existants. La gestion du secret,
trouver des modules django populaires, les noms de dossiers relatifs...
C'est pour moi un bon début.

Faire un fichier d'import de settings/valeurs par défaut dans chaques
projets ayant des options.

Sphinx c'est bien et ça ce couple à merveille avec doctest. (permet de
documenter l'api)

Essayer de garder une cohésion dans les imports. (pas d'import *, importer
les modules toujours sous le même nom quelque soit le fichier)

Si une app a plus de 300 lignes de models/forms/views, ne pas hésiter à
ranger ça en dossiers.

(note, je dis 300 ligne mais c'est très personnel, chacun ses seuils de
tolérance, sachant que s'il n'y a pas de moyen de faire des rapprochement
métier ou d'isoler correctement il vaut mieux ne pas faire).

Après pour ma part deux bonne pratiques sont la veilles technologique et
l'initiative de chercher si ce qu'on veut existe déjà.

N'hésitez pas à me contredire mais je pense que ces pratiques m'ont aidé
dans mon parcourt de débutant. (J'ai commencé django en stage à temps
partiel en Janvier).

Cordialement, Christophe.

2011/9/26 Christophe de saint leger <christophe _AT_ lindev.fr>

> Salut à tous ,
>
> Premier message sur ce forum , et premier projet important utilisant
> Django .
>
> Ma question est simple , selon vous , quelles sont les erreurs
> récurrentes de débutant sous django à éviter ?
>
> Que ce soit au niveau sécurité, structure des modules, x, y, z, ... smile
>
> Merci d'avance pour vos conseils que j'essayerai d'appliquer à la lettre
> smile
>
> Ch.
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
>

Hors ligne

#4 26-09-2011 18:08:31

stopher
Membre
Lieu : Lille
Inscription : 26-09-2011
Messages : 11
Site Web

Re : Best Practice

Julien Bouquillon a écrit :

.se forcer à utiliser les "named urls"

Ok , je vois de quoi tu parles .. même si pour le moment, je n'ai pas encore réellement en tête les avantages des conf url non nommées .
Je vais éplucher la doc pour l'utiliser à bon escient .

Julien Bouquillon a écrit :

.utiliser la django debug toolbar et bien regarder les requêtes sql générées

A .. ça par contre , c'est nouveau pour moi , pas encore entendu parler dans mes docs de références .. en même temps il me reste encore qq pages à lire tongue

Je vais creuser ce point .

Julien Bouquillon a écrit :

.utiliser un vrai serveur http pour les statics

C'est vrai que pour mes premiers tests j'ai un peu galèré à utiliser le serveur de dev pour gérer mes fichiers statics .. j'ai finalement réussi , mais étant habitué à utiliser une vm ressemblant au max au serv de prod , pour mes dev , je vais suivre ton conseil la dessus , ça ne me changera pas beaucoup .

Julien Bouquillon a écrit :

.lire les recos des django "reusable apps" :
http://ericholscher.com/projects/django … tions/app/

C'est noté smile

Julien Bouquillon a écrit :

C'est cloné ..

Julien Bouquillon a écrit :

Bon est bien il me reste plus qu'à assimiler tout ça , merci pour ces précieuses premières pistes déjà très complètes .

Je reste ouvert évidemment à toutes autres suggestions .

Merci encore ,
Ch.

Hors ligne

#5 26-09-2011 18:19:52

Julien Bouquillon
Membre
Inscription : 26-09-2011
Messages : 25

Re : Best Practice

Le 26 septembre 2011 19:08, Christophe de saint leger
<christophe _AT_ lindev.fr>a écrit :

> [quote=Julien Bouquillon]
> .se forcer à utiliser les "named urls"
> [/quote]
>
> Ok , je vois de quoi tu parles .. même si pour le moment, je n'ai pas
> encore réellement en tête les avantages des conf url non nommées .
> Je vais éplucher la doc pour l'utiliser à bon escient .
>

Cela permet d'avoir tes urls définies une seul fois dans urls.py et de ne
les appeler par leur nom et paramètres dans les vues, templates...

ex:dans les templates, au lieu de : <a href="/preview/video/{
object.id}">apercu</a>

tu aurais : <a href="{% url preview-video object.id %}">apercu</a>

cela permet de contrôler les urls depuis urls.py et de pouvoir les changer à
tout moment sans effort.



> [quote=Julien Bouquillon]
> .utiliser la django debug toolbar et bien regarder les requêtes sql
> générées
> [/quote]
>
> A .. ça par contre , c'est nouveau pour moi , pas encore entendu parler
> dans mes docs de références .. en même temps il me reste encore qq pages
> à lire tongue
>
> Je vais creuser ce point .
>

indispensable sinon un jour tu te trouves tres facilement avec 400 req par
page grace/a cause de l'ORM et des templates.
C'est un tres bon moyen de voir ce qui se passe en background et prendre des
bons reflexes des le début



> [quote=Julien Bouquillon]
> .utiliser un vrai serveur http pour les statics
> [/quote]
>
> C'est vrai que pour mes premiers tests j'ai un peu galèré à utiliser le
> serveur de dev pour gérer mes fichiers statics .. j'ai finalement réussi
> , mais étant habitué à utiliser une vm ressemblant au max au serv de
> prod , pour mes dev , je vais suivre ton conseil la dessus , ça ne me
> changera pas beaucoup .
>

pour le dev, tu peux utiliser celui de django, pas de souci (sauf qu'il est
single-thread et lent, mais tu peux tester
https://github.com/ashchristopher/django-concurrent-server ).


si seulement j'avais posté ici au début smile


good luck


ju

Hors ligne

#6 07-10-2011 19:09:43

stopher
Membre
Lieu : Lille
Inscription : 26-09-2011
Messages : 11
Site Web

Re : Best Practice

Julien Bouquillon a écrit :

Cela permet d'avoir tes urls définies une seul fois dans urls.py et de ne
les appeler par leur nom et paramètres dans les vues, templates...

ex:dans les templates, au lieu de : <a href="/preview/video/{
object.id}">apercu</a>

tu aurais : <a href="{% url preview-video object.id %}">apercu</a>

cela permet de contrôler les urls depuis urls.py et de pouvoir les changer à
tout moment sans effort.

Effectivement très pratique

Julien Bouquillon a écrit :

>

Julien Bouquillon a écrit :

> .utiliser la django debug toolbar et bien regarder les requêtes sql
> générées
>

>
> A .. ça par contre , c'est nouveau pour moi , pas encore entendu parler
> dans mes docs de références .. en même temps il me reste encore qq pages
> à lire tongue
>
> Je vais creuser ce point .
>

indispensable sinon un jour tu te trouves tres facilement avec 400 req par
page grace/a cause de l'ORM et des templates.
C'est un tres bon moyen de voir ce qui se passe en background et prendre des
bons reflexes des le début

Bon , mon environnement en place, et django debug toolbar en place .. c'est tout simplement .... indispensable effectivement .. j'aime la simplicité d'utilisation et de mise en place

Julien Bouquillon a écrit :

>

Julien Bouquillon a écrit :

> .utiliser un vrai serveur http pour les statics
>

>
> C'est vrai que pour mes premiers tests j'ai un peu galèré à utiliser le
> serveur de dev pour gérer mes fichiers statics .. j'ai finalement réussi
> , mais étant habitué à utiliser une vm ressemblant au max au serv de
> prod , pour mes dev , je vais suivre ton conseil la dessus , ça ne me
> changera pas beaucoup .
>

pour le dev, tu peux utiliser celui de django, pas de souci (sauf qu'il est
single-thread et lent, mais tu peux tester
https://github.com/ashchristopher/djang … ent-server ).

Bon là , je ne me suis pas trop creusé la tête .. apache et point barre ... apres quelques acrobaties avec STATIC_URL STATIC_ROOT MEDIA_URL et MEDIA_ROOT , utiliser un serveur http standard pour gérer le fichiers statiques est finalement bien plus facile et pratique .... même pour les dev


J'ai creusé pas mal de temps au niveau des context_processors et middleware , pour les ocntext_processors, j'ai déjà trouv" une utilité certaine ( pour mon cas injection de variables dans tous mes templates sans devoir spécifier un paramètre particulier à chaque appel de "render_to_response()"  ).

Par contre , j'ai encre un peu de mal à trouver une utilité évidente au middleware ( personnel ), ceux par défaut sont déjà tres complet .

D'où ma question ,

vous , dans vos développement , avez vous crée vos propres middlewares , pour quels types de traitements ?

Hors ligne

#7 07-10-2011 19:31:45

Julien Bouquillon [revolunet]
Membre
Inscription : 07-10-2011
Messages : 22

Re : Best Practice

Hello

Django debug toolbar est un exemple de middleware

j'ai crée des middleware dans les cas suivants :detection du hostname et
changement du settings des templates pour afficher un template différent en
fonction du hostname.

en fait c'ets pour un site qui a plusieurs themes en fonction du nom de
domaine utilisé et qui utilise des datas differentes. meme code pour
plusieurs sites.

...

hope this helps

ju

Hors ligne

#8 07-10-2011 19:33:40

Christophe, Jean-Charles Narbonne
Membre
Inscription : 23-06-2011
Messages : 30

Re : Best Practice

Pour moi, le middleware est un décorateur de masse, J'ai une classe qui
hérite de django.contribs.auth.User, qui est une classe proxy. si je veux
pourvoir en tirer parti sans travail, le middleware peu le faire.

Je pense que c'est pour ajouter des fonctionnalités à request, faire du
débug ou du controle de sécurité principalement les middleware.

2011/10/7 Christophe de saint leger <christophe _AT_ lindev.fr>

> [quote=Julien Bouquillon]
>
> Cela permet d'avoir tes urls définies une seul fois dans urls.py et de ne
> les appeler par leur nom et paramètres dans les vues, templates...
>
> ex:dans les templates, au lieu de : <a href="/preview/video/{
> object.id}">apercu</a>
>
> tu aurais : <a href="{% url preview-video object.id %}">apercu</a>
>
> cela permet de contrôler les urls depuis urls.py et de pouvoir les
> changer à
> tout moment sans effort.
> [/quote]
>
> Effectivement très pratique
>
> [quote=Julien Bouquillon]
> > [quote=Julien Bouquillon]
> > .utiliser la django debug toolbar et bien regarder les requêtes sql
> > générées
> > [/quote]
> >
> > A .. ça par contre , c'est nouveau pour moi , pas encore entendu parler
> > dans mes docs de références .. en même temps il me reste encore qq
> pages
> > à lire tongue
> >
> > Je vais creuser ce point .
> >
>
> indispensable sinon un jour tu te trouves tres facilement avec 400 req par
> page grace/a cause de l'ORM et des templates.
> C'est un tres bon moyen de voir ce qui se passe en background et prendre
> des
> bons reflexes des le début
>
> [/quote]
>
> Bon , mon environnement en place, et django debug toolbar en place ..
> c'est tout simplement .... indispensable effectivement .. j'aime la
> simplicité d'utilisation et de mise en place
>
> [quote=Julien Bouquillon]
> > [quote=Julien Bouquillon]
> > .utiliser un vrai serveur http pour les statics
> > [/quote]
> >
> > C'est vrai que pour mes premiers tests j'ai un peu galèré à utiliser
> le
> > serveur de dev pour gérer mes fichiers statics .. j'ai finalement
> réussi
> > , mais étant habitué à utiliser une vm ressemblant au max au serv de
> > prod , pour mes dev , je vais suivre ton conseil la dessus , ça ne me
> > changera pas beaucoup .
> >
>
> pour le dev, tu peux utiliser celui de django, pas de souci (sauf qu'il
> est
> single-thread et lent, mais tu peux tester
> [url]https://github.com/ashchristopher/django-concurrent-server[/url] ).
>
> [/quote]
>
> Bon là , je ne me suis pas trop creusé la tête .. apache et point barre
> ... apres quelques acrobaties avec STATIC_URL STATIC_ROOT MEDIA_URL et
> MEDIA_ROOT , utiliser un serveur http standard pour gérer le fichiers
> statiques est finalement bien plus facile et pratique .... même pour les
> dev
>
>
> J'ai creusé pas mal de temps au niveau des context_processors et
> middleware , pour les ocntext_processors, j'ai déjà trouv" une utilité
> certaine ( pour mon cas injection de variables dans tous mes templates sans
> devoir spécifier un paramètre particulier à chaque appel de
> "render_to_response()"  ).
>
> Par contre , j'ai encre un peu de mal à trouver une utilité évidente au
> middleware ( personnel ), ceux par défaut sont déjà tres complet .
>
> D'où ma question ,
>
> vous , dans vos développement , avez vous crée vos propres middlewares ,
> pour quels types de traitements ?
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
>

Hors ligne

#9 07-10-2011 21:01:12

abki
Membre
Lieu : Paris
Inscription : 11-08-2010
Messages : 49
Site Web

Re : Best Practice

Le 7 octobre 2011 20:33, Christophe Narbonne <christophe31 _AT_ gmail.com> a
écrit :

> Pour moi, le middleware est un décorateur de masse, J'ai une classe qui
> hérite de django.contribs.auth.User, qui est une classe proxy. si je veux
> pourvoir en tirer parti sans travail, le middleware peu le faire.
>
> Je pense que c'est pour ajouter des fonctionnalités à request, faire du
> débug ou du controle de sécurité principalement les middleware.
>
>
Les requetes passe au travers des middlewares en arrivant et en sortant de
l'application. Ensuite il suffit de lire les methodes à ta disposition pour
imaginer comment tu peux l'utiliser pour communiquer avec l'application dans
un sens, et avec le reste du monde dans l'autre.

autres cas d'utilisations:
- gestion des entêtes http (entête pour le cache, surement d'autres choses)
- compression des pages et autres modifications sur le corps de la reponse
http

Amirouche

Hors ligne

#10 07-10-2011 21:02:40

abki
Membre
Lieu : Paris
Inscription : 11-08-2010
Messages : 49
Site Web

Re : Best Practice

Le 7 octobre 2011 20:33, Christophe Narbonne <christophe31 _AT_ gmail.com> a
écrit :

> Pour moi, le middleware est un décorateur de masse,


+1, je ne trouve pas mieux que masse mais c'est la bonne idée

Hors ligne

#11 08-10-2011 02:29:35

abki
Membre
Lieu : Paris
Inscription : 11-08-2010
Messages : 49
Site Web

Re : Best Practice

tl;dr: j'introduis deux fichiers par application ``data.py`` et ``core.py``

Une idée que je n'ai pas encore mise en pratique mais qui semble être
prometeuse
pour les grands projets est de wrapper les requetes faites à la db et les
actions
coeur (metier ou business dans d'autres terminologies) de l'applications
dans des
fonctions.

Exemple de vues, niveau intermediaire et mal écrite:

[quote=Python]

# view.py

def answer_message(request, source_message_pk):
    if request.method == POST:
        form = MessageForm(request.POST)
        if form.validate():
            source_message_pk, parent_message_pk, thread_messsage_pk,
message_content = form.cleanned_data
            message = Message(parent=parent_message_pk,
thread=thread_message_pk, content=message_content, user=request.user)
            message.save()
        else:
            initial = {'thread_message_pk':
request.GET.get('thread_message_pk', None),
                       'parent_message_pk':
request.GET.get('parent_message_pk', None)}
            if None in initial.values()
                return HttpBadRequest()
            form = MessageForm(initial=initial)
        login_form = LoginForm()
        return render(request, 'trickypart/message_answer.html',
{'message_form': form, 'login_form': login_form})


def post_message(request):
    if request.method == POST:
        form = MessageForm(request.POST):
        if form.validate():
            source_message_pk, parent_message_pk, thread_messsage_pk,
message_content = form.cleanned_data
            message = Message(parent=parent_message_pk,
thread=thread_message_pk, content=message_content, user=request.user)
            message.save()
        else:
            form = MessageForm() # this is root message, it has no parent
nor thread
        login_form = LoginForm()
        return render(request, 'trickypart/message_post.html',
{'message_form': form, 'login_form': login_form})

[/quote]

Il est possible de factoriser ``login_form = LoginForm()`` avec une
vue-classe [1],
et faire toute la demonstration avec les vues-classes, ce n'est pas ce que
je veux
expliquer (mais se serait interessant).

Les deux vue partage du code exactement identique, il *faut* factoriser.
Dans une fonction ``post_message``
dans un fichier ``core.py`` par exemple (je suis pas certains pour le nom de
fichier ``core``).

Un problème persiste: les arguments. Il y a potentiellement beaucoup
d'argument
à passer et souvent à ralonge ça fait des fonctions moches du style::

[quote=Python]
def ma_uber_fonction_qui_factorise_tout_sur_son_passage(ya, plus, de place,
pour, les, arguments):
    # uber cool content
[/quote]

Au delà de 3 arguments je considère que c'est fatiguant. L'astuce, tiré de
gecko,
est de passer les valeurs du form validé sous forme de dictionnaire ou de
manière plus pythonique,
en utilisant les arguments clef-valeurs aka. **kwargs. Cela donne le
prototype suivant::

[quote=Python]
def jolie_fonction(user, **kwargs): # ou dans la forme étendu en precisant
le nom des clefs attendus
    # Peace an tranquillity to Earth
[/quote]

C'est le prototype de toutes les fonctions de ``core.py``

Elle s'utilise de cette façon::

[quote=Python]
jolie_fonction(user, clef1=valeur1, clef2=valeur2, vers=infini)
[/quote]

où en utilisant un dictionnaire::

[quote=Python]
la_rousse = dict(clef1=valeur1, clef2=valeur2, vers=infini)
jolie_fonction(user, **la_rousse)
[/quote]

Les deux écritures sont équivalentes.

Pour simplifier le code on suppose que les Django forms savent
generer le dictionnaire à notre place à travers la propriété ``clean_dict``,
d'où::

[quote=Python]
form = MyForm(request.POST)
form.is_valid()  # generation de la propriété clean_dict
jolie_fonction(user, **form.clean_dict)
[/quote]

Je reprend mon exemple de départ en appliquant cette API|methode::

[quote: Python]

# view.py

def answer_message(request, source_message_pk):
    if request.method == POST:
        form = MessageForm(request.POST)
        if form.is_valid():
            core.post_message(request.user, **form.clean_dict)
        else:
            initial = {'thread_message_pk':
request.GET.get('thread_message_pk', None),
                       'parent_message_pk':
request.GET.get('parent_message_pk', None)}
            if None in initial.values()
                return HttpBadRequest()
            form = MessageForm(initial=initial)
        login_form = LoginForm()
        return render(request, 'trickypart/message_answer.html',
{'message_form': form, 'login_form': login_form})


def post_message(request):
    if request.method == POST:
        form = MessageForm(request.POST):
        if form.is_valid():
            core.post_message(request.user, **form.clean_dict)
        else:
            form = MessageForm() # this is root message, it has no parent
nor thread
        login_form = LoginForm()
        return render(request, 'trickypart/message_post.html',
{'message_form': form, 'login_form': login_form})


# core.py

def post_message(user, **kwargs):
    data.message_create(
        parent_pk=kwargs.get('parent_message_pk', None),
        thread_pk=kwargs.get('thread_message_pk', None),
        content=kwargs(message_content'),   # A Message without content is
empty
        user=user
    )
    # void

[/quote]

Le module ``data`` est chargé de traiter tous les accès aux données, (c'est
la DAO),
chaque fonction s'éxecute dans une transaction ou en autocommit comme Django
par
défaut à la fin de la requete ou bien encore managé manuellement depuis
``core.py``.
Il viens remplacer les manager de Django, dont je ne vois pas l'interet.

Voici ``data.message_create``::

[quote=Python]
def message_create(parent_pk, thread_pk, content, user):
    message = Message(parent=parent_pk, thread=thread_pk, content=content
    message.save()
[/quote]

Elle ne paye pas de mines et c'est normal car c'est un exemple simple. Un
autre exemple
de fonction ``data`` qui recupère la liste des messages entrant d'un
utilisateur
aka. timeline de chez nos amis des baleines et des oisillions::

[quote=Python]
def messages_for_user(user):
    Message.objects.get(recipient=user)
[/quote]

Pour etayer l'exemple et illustrer un cas d'utilisation de ``data.py``,
l'application
s'ouvre au monde et deviens un reseau social decentralisé. Les messages
entrants
proviennent de plusieurs sources. Le besoin reste le même à savoir récupérer
la liste
des message entrant d'un utilisateur::

[quote=Python]
def messages_for_user(user):
    incoming_messages = []  # ne va contenir que des objets ``Message``
    incoming_messages += Message.objects.get(recipients=user)
    incoming_messages += TwitterAPI.get_timeline(user)[:user.last_checkout]
    incoming_messages += FacebookAPI.get_timeline(user)[:user.last_checkout]
    incoming_messages += HyperAPI.get_timeline(user)[:user.last_checkout]
    incoming_messages = sorted(incoming_messages, key = lambda x:
x.publication_date)
[/quote]

J'ai mis "imaginer" et "naïve" dans deux phrases mitoyennes, c'est un signal
fort
pour faire remarquer que ce n'est pas la bonne solution pour resoudre ce
problème.
Malgré tout l'exemple illustre que l'on peut passer d'un reseau social
centralisé
à un reseau social décentralisé sans changer l'API de l'application (sans
changer
le code des vues, des controleurs ou de ``core.py``).

Un autre exemple est la reecriture de cette même fonction en plus rapide, un
changement
d'ORM, un passage au SQL ou autre, il y a 101 raisons de reécrire cette
fonction.

Bien sur c'est de la théorie. Il faut savoir rester pragramatique [...].
Mais quand il s'agit d'apprendre à programmer, autant prendre l'habitude
d'abstraire, de factoriser et reperer les unités logiques.

Autres conseils:

- venir sur #django-fr sur le reseau irc.freenode.net
- lire le code source de Django
- lire du code, n'importe quoi, cela entraine le cerveau à comprendre,
abstraire,
  resoudre.
- Suivre les conférences, comme la toute recente pycodeconf
- apprendre à utiliser le module logging de Python
- valider les formulaires avec Django et pas à la mano dans les vues...
- RTFM
- STFW
- blogger
- et rendre public sont code en AGPLv3

[1]
https://docs.djangoproject.com/en/dev/topics/class-based-views/#adding-extra-context

Hors ligne

Pied de page des forums