HOWTO - Migration de Wordpress vers Django
Introduction
Wordpress c'est très bien, mais ca devient peu devenir vite une machine à gaz. Mon hébergement gratuit et mutualisé chez 1and1 étant finis, je dois migrer sur un nouveau serveur, et PHP, pour moi c'est révolu, autant passer à Django, et décrire la marche à suivre.
Nous n'allons pas voir comment créer un systeme de blog en Django, beaucoup d'applications disponible sur le web et écrite en Django le font déjà très bien, nous allons donc voir comment appréhender le problème d'une migration entre un outil PHP/MySQL vers Django.
Le système de publication des news sera donc libre, pour ma part, je compte utiliser un systeme développé par et pour moi meme nommé Zinnia.
Nous allons donc voir comment migrer ses données de manieres efficace pour bénéficier de la puissance de Python. :)
Préparation
Récupérez un backup de sa base de donnée Wordpress, généralement sous MySQL, dans mon cas, j'ai utilisé PhpMyAdmin pour faire cela.
Installez ensuite votre backup sur votre machine en local sous MySQL, le but étant d'utiliser temporairement cette base, pour ensuite migrer sous un n'importe quel type de serveur de base de donnée.
On peut injecter le backup de cette manière.
$> mysql -p < backup_wordpress.sql
Création du projet
On va désormais créer un nouveau projet en Django qui contiendra tout le code du nouveau site.
$> django-admin startproject mywebsite
Ce projet contiendra différentes applications Django, dont le moteur de blog, l'application de migration de Wordpress et tout ce que le site aura besoins en terme de fonctionalités.
Migration
Nous allons ensuite créer une application qui va contenir tout le code pour effectuer la migration, c'est à dire les models, et la moulinette qui va servir de transition.
$> cd mywebsite/
$> python manage.py startapp wordpress2django
Directement nous allons installer notre nouvelle application dans le fichier settings.py de notre projet.
>>> INSTALLED_APPS = (
... 'django.contrib.auth',
... 'django.contrib.contenttypes',
... 'django.contrib.sessions',
... 'django.contrib.sites',
... 'mywebsite.wordpress2django',
... )
Les models
On va désormais récupérer la structure de la base de donnée du backup Wordpress, pour en extraire les models.
Pour cela dans le fichier settings.py nous allons le configurer pour qu'il puisse accéder à la base de donnée MySQL où nous avons installer notre backup de Wordpress.
Dès que cela est fait, nous allons utiliser la commande suivante pour récuperer les models.
$> python manage.py inspectdb > wordpress2django/models.py
Bien entendu, les models que vous allez obtenir seront différents d'une version de Wordpress à l'autre, et aussi en fonction des plugins installés.
Désormais si on rentre dans le shell de Django, on peux acceder aux models de Wordpress de maniere pythonique.
$> python manage.py shell
>>> from mywebsite.wordpress2django.models import WpUsers
>>> from mywebsite.wordpress2django.models import WpPosts
>>> WpUsers.objects.count()
... 42L
>>> WpPosts.objects.count()
... 127L
Corrections
Vous allez vous rendre compte que les champs ID exportés par la commande inspectdb posent problèmes, c'est mon cas sur la plupart des models, donc nous allons rajouter la proprieté primary_key=True sur ces champs, l'exemple sur WpPosts et WpCategories.
>>> class WpPosts(models.Model):
... id = IntegerField(primary_key=True)
...
>>> class WpCategories(models.Model):
... cat_id = IntegerField(primary_key=True)
D'autres corrections seront certainement nécessaires pour pouvoir faire fonctionner complètement les models.
Améliorations
Je vous conseille si vous compter utiliser souvent ces models de leur définir une méthode __unicode__ à chacun, pour en faciliter l'usage, par exemple pour WpPosts.
>>> class WpPosts(models.Model):
... def __unicode__(self):
... return '%s: %s' % (self.id, self.post_title)
Backuping
Une bonne idée serait de dumper notre base, avec ses données dans un format serialisé, et indépendant du systeme de base de donnée, et facilement intelligible par Django, en cas de mauvaises manipulations pendant la conception de la moulinette de transition.
Le mieux étant de toujours avoir cette copie à disposition, et rechargée à chaque synchronisation de la base de donnée durant nos tests de développement. On va donc créer un repertoire fixtures dans notre application wordpress2django, et effectuer un dump.
$> mkdir wordpress2django/fixtures
$> python manage.py dumpdata wordpress2django > wordpress2django/fixtures/initial_data.json
Nommé ainsi et à cet emplacement le dump au format JSON sera rechargé à chaques synchronisations de la base de donnée.
Ensuite il sera aisé de supprimer ces données en mode production avec la commande suivante qui va nous fournir un script de nettoyage.
$> python manage.py sqlclear wordpress2django
Synchronisation
Désormais, ce qui serait cool, c'est de finir de s'émanciper de MySQL pour commencer notre moulinette qui migrera nos données d'une applications à l'autre.
Pour cela on va changer les informations de connection à la base de donnée dans notre fichier settings.py. Je vous conseille de le faire sur SQLite3, qui permet beaucoup de souplesses surtout en période de développement.
Ensuite, on va effectuer, un syncdb, et nous allons retrouver nos futures anciennes données. :)
$> python manage.py syncdb
Tant que cette étape ne passe pas, c'est que les models ne sont pas encore bon. Il est nécessaire de les faire fonctionner avant de passer à la suite.
Moulinette
Commande
Désormais programmons la moulinette, pour cela on va écrire un script python qui va faire la transition entre les 2 jeux de models. Le premier jeu étant celui de l'application wordpress2django, les models de Wordpress, et le second jeu de models est bien entendu celui de notre nouveau système de blog.
Au lieu d'écrire ce script n'importe où, nous allons le stocker dans le répertoire wordpress2django/management/commands, qui permettra de le rentre accessible de partout depuis notre projet. Il sera appeler wp2zinnia.
$> mkdir -p wordpress2django/management/commands/
$> touch wordpress2django/management/__init__.py
$> touch wordpress2django/management/commands/__init__.py
$> touch wordpress2django/management/commands/wp2zinnia.py
Désormais si on execute la commande :
$> python manage.py help
Nous voyons donc notre commande wp2zinnia disponible. L'avantage de ce système, c'est qu'il va automatiquement charger la configuration du fichier settings.py, donc la base de donnée, pas besoin d'en faire plus.
Ensuite on va créer un objet qui va nous servir de commande. Donc tapons ceci dans notre fichier wp2zinnia.py.
>>> from django.core.management.base import NoArgsCommand
>>>
>>> class Command(NoArgsCommand):
... help = 'Migration data command of wordpress 2.1.2 to a django app'
...
... def handle_noargs(self, **options):
... pass
La méthode handle_noargs sera le point d'entrée de notre script.
Migration des utilisateurs
La première des choses à faire serait de migrer les utilisateurs sur le module auth de Django, qui fournira les mêmes fonctionnalitées que Wordpress.
D'abord vérifier que django.contrib.auth est présent dans la section INSTALLED_APPS de votre fichier settings.py.
Ensuite si je regarde les données que j'ai insérées grâce à mon backup, je remarque que j'ai des utilisateurs que je ne veux pas insérer, que les mots de pass sont encodés, donc perdus, et que je vais devoir assigner des groupes à mes utilisateurs.
Je pourrais très bien coder cela, mais finalement, je vais juste rien faire :).
Vu que j'ai déjà créer mon super utilisateur lors du syncdb, je peux rérentrer facilement mes anciens contributeurs, et les associer à des groupes à travers le module d'administration de Django.
Cette solution me semble plus souple et facile pour cette étape de la migration.
Migrations des catégories
Une des choses les plus faciles à faire, pour ce script c'est de transférer les catégories de Wordpress. En assumant que nous avons le model de catégorie suivant dans l'application Zinnia.
>>> class Category(models.Model):
... title = models.CharField( max_length=50)
... slug = models.SlugField()
... description = models.TextField(blank=True)
Nous allons entrer cette méthode dans notre objet Command qui devra être appelée depuis la méthode handle_noargs.
>>> def migrate_categories(self):
... """Duplicate WPcategories to zinnia categories"""
... for wpcategory in WpCategories.objects.all():
... category, created = Category.objects.get_or_create(title=wpcategory.cat_name,
... slug=wpcategory.category_nicename,
... description=wpcategory.category_description)
... print 'Inserting category : %s' % wpcategory.cat_name
Nous faisons juste une boucle autours des catégories de Wordpress, pour insérer les informations qui nous interessent dans nos nouveaux models.
Pour les articles, c'est le même procédés hormis qu'ils faudra les associer aux catégories.
En espérant vous avoir guider à travers le processus de migration de Wordpress vers Django et le Python.
Pour voir la commande de migration complète pour Zinnia, suivez ce lien.