14-01-2016, 19:21
Creme1.6 est une version dont la majorité des changements interviennent sous le capot. Ces changements sont avant tout du au passage à Django1.8 (Creme1.5 utilisant Django 1.4) comme nous allons le voir. Aussi si vous avez développé vos propres modules Creme, il y a toutes les chances que vous deviez mettre à jour votre code. Ce post est là pour vous y aider ; n'hésiter pas poser des questions, car ne post ne pourra jamais être totalement complet.
Tout d'abord sachez que le tutoriel d'écriture de module, présent dans le répertoire /doc/fr, a été mis à jour. Bon nombre d'informations de ce post proviendront de ce didacticiel.
N'hésitez pas à aller lire les changelogs des différentes versions de Django, notamment lorsqu'une méthode de Django a disparu ou bien déclenche des warnings 'deprecated'.
https://docs.djangoproject.com/en/1.8/releases/1.5/
https://docs.djangoproject.com/en/1.8/releases/1.6/
https://docs.djangoproject.com/en/1.8/releases/1.7/
https://docs.djangoproject.com/en/1.8/releases/1.8/
Vous devriez aussi aller lire le fichier CHANGELOG.txt à la racine des sources de Creme. Les différents changements y sont listés, en séparant ceux qui cassent la compatibilité avec la version précédente, et ceux qui ne la casse pas (mais peuvent provoquer des warnings lorsque leur suppression est prévue dans une version ultérieure).
Changements principaux au niveau de Django
Classe de configuration
Votre fichier 'creme_core_register.py' n'est plus pris en compte ; nous utilisons à présent le système de configuration d'app (apparu dans Django 1.8). Créez un fichier 'apps.py' à la racine de votre app, et créez une classe dérivant de 'creme.creme_core.apps.CremeAppConfig'. Le tutoriel vous explique comment faire la plupart des choses que vous faisiez avant avec 'creme_core_register.py' (enregistrer l'app, les entités, le menu ...).
N'oubliez pas de définir dans le __init__.py de votre app la variable 'default_app_config', de manièere à indiquer votre classe comme configuration (ex: "creme.my_app.apps.MyAppConfig").
Les URLs
Dans votre fichier 'urls.py', les listes d'URLs devraient maintenant être de simples listes (et non plus des objets 'django.conf.urls.patterns'), et les vues devraient être référencées directement (et non plus être sous forme de strings).
Les migrations
Vous pouvez supprimer votre ancien répertoire 'migrations/'. Créez de nouvelles migrations grâce à la commande "python manage.py makemigrations my_app". Sur votre base de production, l'idée est de faire comme si cette migration avait été exécutée (puisque les tables existent déjà) avec "python manage.py migrate my_app --fake-initial" ; c'est d'ailleurs ce que vous faites pour passer une base 1.5 à 1.6 de manière générale.
get_create_absolute_url()
Vos modèles d'entités devraient implémenter la méthode 'get_create_absolute_url()', qui renvoie l'URL de création de ce type d'entités.
Le nouveau modèle utilisateur
Le modèle utilisateur dans creme n'est plus 'auth.models.User' mais 'creme.creme_core.models.auth.CremeUser' ; ceci dit n'importez pas cette classe directement. Utilisez la variable 'settings.AUTH_USER_MODEL' (dans la définition de vos ForeignKey par exemple) ou bien la fonction django.contrib.auth.get_user_model() afin d'obtenir le modèle utilisé concrètement (ce qui vous permettrait de modifier dans l'absolu le modèle utilisateur qui doit être utilisé).
Le swapping de modèles
La façon de modifier les modèles existants (comme Contact) a été complètement revue, afin d'être compatible avec les nouvelles version de Django et de fournir un outil plus puissant par bien des aspects.
En revanche la mauvaise nouvelle c'est que cela demande un peu plus de travail lorsque vous voulez juste faire une modification mineure pour rajouter un champ (mais à long terme vous devriez y gagner, par exemple pour migrer vers une version plus récente sans conflit). C'est parce que la fonction 'contribute_to_model()' a disparu.
La première conséquence est que si votre code importe la classe 'Contact' par exemple, vous devriez plutôt utiliser la fonction 'creme.persons.get_contact_model()' (ou bien la variable 'settings.PERSONS_CONTACT_MODEL' lorsque vous définissez une ForeignKey par exemple).
La seconde conséquence c'est que maintenant, si vous voulez modifier Contact, vous devez écrire votre propre classe de contact (mais il existe une classe 'persons.models.AbstractContact' qui vous permet de n'avoir presque rien à faire au final, à part ajouter les champs qui vous intéresse), puis dans 'settings.py' configurer la variable 'PERSONS_CONTACT_MODEL' afin de pointer vers votre propre classe.
Tout ceci est décrit plus précisément dans le tutoriel, au chapitre "Modification d'un modèle existant". Il y a notamment une partie "Comment swapper un modèle à posteriori ?", qui vous aidera à migrer votre code et votre base de données lorsque vous avez utilisé 'contribute_to_model()' auparavant.
Tout d'abord sachez que le tutoriel d'écriture de module, présent dans le répertoire /doc/fr, a été mis à jour. Bon nombre d'informations de ce post proviendront de ce didacticiel.
N'hésitez pas à aller lire les changelogs des différentes versions de Django, notamment lorsqu'une méthode de Django a disparu ou bien déclenche des warnings 'deprecated'.
https://docs.djangoproject.com/en/1.8/releases/1.5/
https://docs.djangoproject.com/en/1.8/releases/1.6/
https://docs.djangoproject.com/en/1.8/releases/1.7/
https://docs.djangoproject.com/en/1.8/releases/1.8/
Vous devriez aussi aller lire le fichier CHANGELOG.txt à la racine des sources de Creme. Les différents changements y sont listés, en séparant ceux qui cassent la compatibilité avec la version précédente, et ceux qui ne la casse pas (mais peuvent provoquer des warnings lorsque leur suppression est prévue dans une version ultérieure).
Changements principaux au niveau de Django
- Un système de migration intégré, qui supprime le besoin d'utiliser l'app externe South ; les anciennes migrations South sont incompatibles, de nouvelles migrations doivent donc être écrites/générées. Ce point est développé plus bas.
- Les apps doivent avoir une classe de configuration. Ce point est développé plus bas.
- L'ancienne façon décrire les fichiers urls.py est obsolète. Ce point est développé plus bas.
- L'objet _meta de vos modèles a changé ; par exemple la méthode get_field_by_name() est obsolète, get_field() doit lui être préféré.
- Différents moteurs de templates peuvent être utilisés ; bien que Creme utilise toujours le même moteur (pour le moment en tout cas), cela a entraîné des changements d'API dans Django. La principale différence est que le contexte devrait être un dictionnaire classique, et non plus un RequestContext. Si vous avez défini vos propres vues, vous devriez vous en soucier.
- La classe Meta de vos formulaires de modèles doivent avoir un attribut 'fields' (ou bien 'exclude').
- Changement du fonctionnement des transactions ; en général utiliser transaction.atomic() à la place de transaction.commit_on_success()/transaction.commit_manually()/transaction.savepoint*() suffira amplement.
- La façon dont les tests unitaires sont organisés a changé; si vous utilisez un répertoire 'tests/', il n'y a plus besoin de tous les importer à la racine, en revanche vos noms de fichiers doivent commencer par 'test_'.
- La bibliothèque 'django.utils.simplejson' a été supprimée ; utilisez 'json'.
- La bibliothèque 'django.forms.util' a été renommée 'django.forms.utils'.
Classe de configuration
Votre fichier 'creme_core_register.py' n'est plus pris en compte ; nous utilisons à présent le système de configuration d'app (apparu dans Django 1.8). Créez un fichier 'apps.py' à la racine de votre app, et créez une classe dérivant de 'creme.creme_core.apps.CremeAppConfig'. Le tutoriel vous explique comment faire la plupart des choses que vous faisiez avant avec 'creme_core_register.py' (enregistrer l'app, les entités, le menu ...).
N'oubliez pas de définir dans le __init__.py de votre app la variable 'default_app_config', de manièere à indiquer votre classe comme configuration (ex: "creme.my_app.apps.MyAppConfig").
Les URLs
Dans votre fichier 'urls.py', les listes d'URLs devraient maintenant être de simples listes (et non plus des objets 'django.conf.urls.patterns'), et les vues devraient être référencées directement (et non plus être sous forme de strings).
Les migrations
Vous pouvez supprimer votre ancien répertoire 'migrations/'. Créez de nouvelles migrations grâce à la commande "python manage.py makemigrations my_app". Sur votre base de production, l'idée est de faire comme si cette migration avait été exécutée (puisque les tables existent déjà) avec "python manage.py migrate my_app --fake-initial" ; c'est d'ailleurs ce que vous faites pour passer une base 1.5 à 1.6 de manière générale.
get_create_absolute_url()
Vos modèles d'entités devraient implémenter la méthode 'get_create_absolute_url()', qui renvoie l'URL de création de ce type d'entités.
Le nouveau modèle utilisateur
Le modèle utilisateur dans creme n'est plus 'auth.models.User' mais 'creme.creme_core.models.auth.CremeUser' ; ceci dit n'importez pas cette classe directement. Utilisez la variable 'settings.AUTH_USER_MODEL' (dans la définition de vos ForeignKey par exemple) ou bien la fonction django.contrib.auth.get_user_model() afin d'obtenir le modèle utilisé concrètement (ce qui vous permettrait de modifier dans l'absolu le modèle utilisateur qui doit être utilisé).
Le swapping de modèles
La façon de modifier les modèles existants (comme Contact) a été complètement revue, afin d'être compatible avec les nouvelles version de Django et de fournir un outil plus puissant par bien des aspects.
En revanche la mauvaise nouvelle c'est que cela demande un peu plus de travail lorsque vous voulez juste faire une modification mineure pour rajouter un champ (mais à long terme vous devriez y gagner, par exemple pour migrer vers une version plus récente sans conflit). C'est parce que la fonction 'contribute_to_model()' a disparu.
La première conséquence est que si votre code importe la classe 'Contact' par exemple, vous devriez plutôt utiliser la fonction 'creme.persons.get_contact_model()' (ou bien la variable 'settings.PERSONS_CONTACT_MODEL' lorsque vous définissez une ForeignKey par exemple).
La seconde conséquence c'est que maintenant, si vous voulez modifier Contact, vous devez écrire votre propre classe de contact (mais il existe une classe 'persons.models.AbstractContact' qui vous permet de n'avoir presque rien à faire au final, à part ajouter les champs qui vous intéresse), puis dans 'settings.py' configurer la variable 'PERSONS_CONTACT_MODEL' afin de pointer vers votre propre classe.
Tout ceci est décrit plus précisément dans le tutoriel, au chapitre "Modification d'un modèle existant". Il y a notamment une partie "Comment swapper un modèle à posteriori ?", qui vous aidera à migrer votre code et votre base de données lorsque vous avez utilisé 'contribute_to_model()' auparavant.