Développer une application tierce Django ======================================== Pytong, Toulon 22 Juin 2013 - Lightning Talk Samuel Goldszmidt ([@ouhouhsami](https://twitter.com/ouhouhsami)), Ircam --- Le besoin --------- > Avant de *développer* : *concevoir*, et encore avant : *exprimer le besoin* > " *Intuitif* " n'est pas un besoin accepté par les maisons sérieuses Un **champ d'auto-complétion** autorisant un ou plusieurs choix : * Performant pour des grands nombres de données * Accessible (mobiles, postes fixes) * Branché sur l'écosystème Django (notre environnement technique de départ) : * Utilisant Django (si besoin les [paquets de contrib](https://docs.djangoproject.com/en/dev/ref/contrib/), intégrable dans l'admin) et des applications tierces solides/reconnues * Respect des bonnes pratiques (Django et Python, organisation du code, doc, tests) --- L'existant ---------- Les *alternatives* déjà existantes : * [django-autocomplete-light](http://django-autocomplete-light.readthedocs.org/en/latest/) (anciennement [django-autocomplete](http://code.google.com/p/django-autocomplete/)) * [django-select2](http://django-select2.readthedocs.org/en/latest/) * [django-ajax-selects](https://github.com/crucialfelix/django-ajax-selects/) * [quelques autres ici](https://www.djangopackages.com/grids/g/auto-complete/) > " Pour des choix éclairés, je consulte [djangopackages](https://www.djangopackages.com) " En terme d'*ergonomie fonctionnelle* : * la librairie Javascript [Select2](http://ivaynberg.github.io/select2/) convenait * son intégration à Django existait déjà : [django-select2](http://django-select2.readthedocs.org/en/latest/) ... mais son usage s'est relevé difficile. --- Les "erreurs" ------------- Quelques retours d'expérience sur le code source * django-select2 : * très monolithique (notamment la gestion de la configuration Javascript, repassant par Python) * [beaucoup de classes](http://django-select2.readthedocs.org/en/latest/ref_widgets.html) * configuration/paramétrage des "fournisseurs de contenu" complexe * Select2 : * non testé * API pas très stabilisée > " Untested code is broken code " --- Les besoins de l'implémentation ------------------------------- Pour réaliser une fonctionnalité d'auto-complétion, il faut : * Côté Javascript : 1. Faire une requête AJAX avec 1 à n paramètres 2. Récupérer un json simple ```[(id, label), ...]``` de données qui permettraient de remplir les ```<option>```d'un champs ```<select>```) 3. Afficher le résultat * Côté Django : 1. "Attraper" une requête AJAX avec 1 à n paramètres 2. Répondre, via json.dumps avec a minima : ```[(id, label), ...]``` ou possiblement ```[(id, label, *args, **kwargs), ...]``` pour ajouter url, contenttype Le reste est en dehors du périmètre initial. > "Autocomplete for humans" > Tu t'es vu quand t'as embauché une rockstar, un ninja et un guru alors qu'un dev t'aurait suffit - cf. [SEO Rockstar](http://www.youtube.com/watch?v=oNgkwkIQZH8)) --- Le développement ---------------- * Copier l'organisation du code de Django, particulièrement [le module forms](https://github.com/django/django/tree/master/django/forms) * Les conventions d'écriture [PEP8](http://www.python.org/dev/peps/pep-0008/) * Les tests et l'intégration continue, par exemple [Travis CI](https://travis-ci.org/), [drone.io](https://drone.io/) * Une doc (a minima un README) * [Le packaging d'application Django](https://docs.djangoproject.com/en/dev/intro/reusable-apps/) (et [pour les téméraires, les différences entre distribute, distutils, setuptools, distutils2](http://stackoverflow.com/questions/6344076/differences-between-distribute-distutils-setuptools-and-distutils2)) > " Etre fainéant, ce n'est pas si simple " Pour cette version de *validation du principe* : * Reparti de la base de tests de django-select2 * Tout cassé, réordonné sur le modèle du code source de Django * Pour aller droit au but (et avoir moins à tester), basé sur 2 applications tierces : 1. [django-floppyforms](http://django-floppyforms.readthedocs.org/en/latest/) - *Full control of form rendering in the templates* Permet de traiter le code Javascript dans un [template : ajax_select2.html](https://github.com/ouhouhsami/django-select2light/blob/master/select2light/templates/select2light/ajax_select2.html) 2. [django-tastypie](http://django-tastypie.readthedocs.org/en/latest/) - *Creating delicious APIs for Django apps since 2010* Permet d'interroger les modèles via Ajax et de récupérer un json via [un fichier api.py](https://github.com/ouhouhsami/django-select2light/blob/master/testapp/testapp/testmain/api.py) --- La conclusion et la suite ------------------------- Pour une version "définitive", les seules briques nécessaires : * côté HTML : champs input hidden (avec pk) * côté Javascript : l'appel Ajax à l'url qui retourne le(s) données * côté Django : une url accessible via url value name En vrac, des idées pour la suite : * HTML5 ```<datalist>``` (se passer de select2) * côté widget HTML, prendre appui sur admin raw_id ([ForeignKeyRawIdWidget](https://github.com/django/django/blob/master/django/contrib/admin/widgets.py#L130) & [ManyToManyRawIdWidget](https://github.com/django/django/blob/master/django/contrib/admin/widgets.py#L188)) * git submodules si des dépendances js ? > "Le bazooka n'est pas celui qu'on croit"