diff --git a/update.md b/update.md index afd419f3c3..1b80c0057c 100644 --- a/update.md +++ b/update.md @@ -306,7 +306,7 @@ et de les écarter temporairement (en les déplacant dans un autre dossier), afi - La recherche nécessite que les données dans la base soit encodées avec un charset "utf8_general_ci" mais tout type de charset utf8 semble correspondre. Pour vérifier que la base de données et les tables sont encodées avec un charset UTF-8, vous pouvez saisir la commande suivante (ne pas oublier de remplir le nom de la base de données dans le `WHERE`): ```sql - SELECT T.table_name, CCSA.character_set_name FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA WHERE CCSA.collation_name = T.table_collation AND T.table_schema ="REMPLACER PAR LE NOM DE LA BASE DE DONNEES"; + SELECT T.table_name, CCSA.character_set_name FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA WHERE CCSA.collation_name = T.table_collation AND T.table_schema ="REMPLACER PAR LE NOM DE LA BASE DE DONNEES"; ``` Si dans la deuxième colonne, il apparait autre chose que le mot "utf8_general_ci", appliquez la commande suivante (remplacez les mots `dbname`, `dbusername` et `dbpassword` par respectivement le nom de la base, le nom de l'utilisateur qui a les droits de modifier la base et son mot de passe): ```bash @@ -490,7 +490,14 @@ la clé dans le fichier de configuration de production. ZEP-25 ------ -Avant toute chose il faut avoir lancé les migrations. La commande `python manage.py migrate_to_zep25` permet de migrer automatiquement les contenus et de notifier les auteurs. Les logs sont très détaillés. En cas de contenus non-migrés automatiquement il y aura un message à la fin ainsi que des `[WARNING]` dans les logs. **La commande peut être assez longue.** +Il faut dans un premier temps supprimer les restes des tables des articles et tutoriels avant la ZEP-12 : + +```sql +DROP TABLE article_article_subcategory; +DROP TABLE tutorial_tutorial_subcategory; +``` + +Avant de continuer il faut s'assurer d'avoir lancé les migrations. La commande `python manage.py migrate_to_zep25` permet de migrer automatiquement les contenus et de notifier les auteurs. Les logs sont très détaillés. En cas de contenus non-migrés automatiquement il y aura un message à la fin ainsi que des `[WARNING]` dans les logs. **La commande peut être assez longue.** Les contenus non migrés automatiquement doivent l'être fait à la main, par les auteurs ou les validateurs. Seuls les contenus publiés sont migrés automatiquement. @@ -516,3 +523,4 @@ Le déploiement doit être autonome. Ce qui implique que : 1. La mise à jour de dépendances est automatique et systématique, 2. La personne qui déploie ne doit pas réfléchir (parce que c'est source d'erreur), 3. La personne qui déploie ne doit pas avoir connaissance de ce qui est déployé (techniquement et fonctionnellement). + diff --git a/zds/tutorialv2/management/commands/migrate_to_zep25.py b/zds/tutorialv2/management/commands/migrate_to_zep25.py index c503611bfd..e8f9b50cf3 100644 --- a/zds/tutorialv2/management/commands/migrate_to_zep25.py +++ b/zds/tutorialv2/management/commands/migrate_to_zep25.py @@ -5,10 +5,10 @@ from django.db import transaction from django.shortcuts import get_object_or_404 from django.utils.encoding import smart_text -from django.utils.text import slugify from zds import settings -from zds.tutorialv2.models.models_database import PublishableContent +from zds.tutorialv2.models.models_database import PublishableContent, PublishedContent +from zds.utils import slugify from zds.utils.models import Category, SubCategory, CategorySubCategory, Tag from zds.utils.mps import send_mp @@ -24,18 +24,20 @@ def categories_to_tags(): for content in contents: categories = content.subcategory.all() for cat in categories: - tag_title = smart_text(cat.slug.replace('-', ' ').strip().lower()) - current_tag = Tag.objects.filter(title=tag_title).first() - if current_tag is None: - current_tag = Tag(title=tag_title) - current_tag.save() - print('[ZEP-25] : Tag "{}" added'.format(current_tag)) - n += 1 - # do not add "autre" tag (useless) - if current_tag != 'autre': - content.tags.add(current_tag) + tag_title = smart_text(cat.slug.replace(u'-', u' ').strip().lower()) + tag_slug = slugify(tag_title) + if len(tag_title) <= 20: + current_tag = Tag.objects.filter(slug=tag_slug).first() + if current_tag is None: + current_tag = Tag(title=tag_title, slug=tag_slug) + current_tag.save() + print(u'[ZEP-25] : Tag "{}" added'.format(current_tag)) + n += 1 + # do not add "autre" tag (useless) + if current_tag != u'autre': + content.tags.add(current_tag) content.save() - print('[ZEP-25] : {} new tag(s)'.format(n)) + print(u'[ZEP-25] : {} new tag(s)'.format(n)) def update_categories(): @@ -44,55 +46,59 @@ def update_categories(): :return: None """ + for cat in CategorySubCategory.objects.all(): + print(u'[ZEP-25] : Try to delete relation "{}" <--> "{}"'.format(cat.subcategory, cat.category)) + cat.delete() + print(u'[ZEP-25] : Relation "{}" <--> "{}" deleted'.format(cat.subcategory, cat.category)) for cat in SubCategory.objects.all(): - print('[ZEP-25] : Old category "{}" deleted'.format(cat)) + print(u'[ZEP-25] : Try to delete old category "{}"'.format(cat)) cat.delete() + print(u'[ZEP-25] : Old category "{}" deleted'.format(cat)) for cat in Category.objects.all(): - print('[ZEP-25] : Old subcategory "{}" deleted'.format(cat)) - cat.delete() - for cat in CategorySubCategory.objects.all(): + print(u'[ZEP-25] : Try to delete old subcategory "{}"'.format(cat)) cat.delete() - print('[ZEP-25] : Categories and subcatagories deleted') - categories = ['Informatique', 'Sciences de la nature', 'Sciences humaines et sociales', 'Autres'] + print(u'[ZEP-25] : Old subcategory "{}" deleted'.format(cat)) + print(u'[ZEP-25] : Categories and subcatagories deleted') + categories = [u'Informatique', u'Sciences de la nature', u'Sciences humaines et sociales', u'Autres'] subcategories = [ # Informatique [ - ('Bureautique et rédaction', 'Excel, LaTeX, Powerpoint, Word'), - ('Matériel et électronique', 'Arduino, Disque dur, DIY, Electronique*, Mémoires, Ordinateur'), - ('Programmation et algorithmique', '.NET, Ada, Algorithmique, C, C#, C++, Cobol, Fonctionnel, Génie logicie' - 'l, Haskell, Java, Julia, Lisp, Ocaml, Orienté objet, Python, Ruby, Vers' - 'ioning'), - ('Site web', 'Accessibilité, Actionscript, Angular JS, CakePHP, Django, HTML/CSS, Java EE, JavaScript, Ngin' - 'x, Node.js, Oxygen, PHP, Ruby On Rails, SEO/Réferencement*, Symfony, Websocket'), - ('Systèmes d\'exploitation', 'Android, GNU/Linux, iOS, MAC OS, Windows, Windows Phone'), - ('Autres (informatique)', 'API, Base de données, FTP, Jeux vidéos, MySQL, Oracle, Protocole, Sécurité, TCP/' - 'IP'), + (u'Bureautique et rédaction', u'Excel, LaTeX, Powerpoint, Word'), + (u'Matériel et électronique', u'Arduino, Disque dur, DIY, Electronique*, Mémoires, Ordinateur'), + (u'Programmation et algorithmique', u'.NET, Ada, Algorithmique, C, C#, C++, Cobol, Fonctionnel, Génie logic' + u'iel, Haskell, Java, Julia, Lisp, Ocaml, Orienté objet, Python, Ruby, ' + u'Versioning'), + (u'Site web', u'Accessibilité, Actionscript, Angular JS, CakePHP, Django, HTML/CSS, Java EE, JavaScript, Ng' + u'inx, Node.js, Oxygen, PHP, Ruby On Rails, SEO/Réferencement*, Symfony, Websocket'), + (u'Systèmes d\'exploitation', u'Android, GNU/Linux, iOS, MAC OS, Windows, Windows Phone'), + (u'Autres (informatique)', u'API, Base de données, FTP, Jeux vidéos, MySQL, Oracle, Protocole, Sécurité, TC' + u'P/IP'), ], # Sciences de la nature [ - ('Astronomie', 'Astronomie'), - ('Géologie et géographie physique', 'Géologie'), - ('Biologie', 'Biologie'), - ('Physique', 'Physique'), - ('Chimie', 'Chimie'), - ('Mathématiques', 'Mathématiques'), - ('Autres (sciences de la nature)', 'Autres sciences de la nature') + (u'Astronomie', u'Astronomie'), + (u'Géologie et géographie physique', u'Géologie'), + (u'Biologie', u'Biologie'), + (u'Physique', u'Physique'), + (u'Chimie', u'Chimie'), + (u'Mathématiques', u'Mathématiques'), + (u'Autres (sciences de la nature)', u'Autres sciences de la nature') ], # Sciences humaines et sociales [ - ('Droit', 'Droit'), - ('Histoire', 'Histoire'), - ('Langues', 'Langues'), - ('Psychologie', 'Psychologie, Pédagogie'), - ('Économie', 'Économie'), - ('Autres (sciences humaines et sociales)', 'Autres sciences humaines et sociales comme la géographie') + (u'Droit', u'Droit'), + (u'Histoire', u'Histoire'), + (u'Langues', u'Langues'), + (u'Psychologie', u'Psychologie, Pédagogie'), + (u'Économie', u'Économie'), + (u'Autres (sciences humaines et sociales)', u'Autres sciences humaines et sociales comme la géographie') ], # Autres [ - ('Arts, graphisme et multimédia', 'Graphisme 2D, Graphisme 3D, Musique, Son'), - ('Communication et management', 'Monde du travail'), - ('Zeste de Savoir', 'Zeste de Savoir'), - ('Autres', 'Littérature, Interview') + (u'Arts, graphisme et multimédia', u'Graphisme 2D, Graphisme 3D, Musique, Son'), + (u'Communication et management', u'Monde du travail'), + (u'Zeste de Savoir', u'Zeste de Savoir'), + (u'Autres', u'Littérature, Interview') ] ] i = 0 @@ -103,19 +109,19 @@ def update_categories(): cat.position = i cat.slug = slugify(u'{}'.format(category)) cat.save() - print('[ZEP-25] : New category "{}" added'.format(cat)) + print(u'[ZEP-25] : New category "{}" added'.format(cat)) for subcategory in subcategories[i]: sub = SubCategory() sub.title = subcategory[0] sub.subtitle = subcategory[1] sub.slug = slugify(u'{}'.format(subcategory[0])) sub.save() - print('[ZEP-25] : New subcategory "{}" added'.format(sub)) + print(u'[ZEP-25] : New subcategory "{}" added'.format(sub)) catsubcat = CategorySubCategory() catsubcat.category = cat catsubcat.subcategory = sub catsubcat.save() - print('[ZEP-25] : Relation "{}" <--> "{}" added'.format(cat, sub)) + print(u'[ZEP-25] : Relation "{}" <--> "{}" added'.format(cat, sub)) i += 1 @@ -156,7 +162,7 @@ def alert_authors(): 'Ce qui change pour vous en tant qu\'auteur', msg ) - print('[ZEP-25] : PM send to {}'.format(user)) + print(u'[ZEP-25] : PM send to {}'.format(user)) def migrate_zds(): @@ -171,43 +177,43 @@ def migrate_zds(): # LAST UPDATE : 20/03/2016 10:30 contents = { # Informatique - 'Bureautique et rédaction': [244, 409, 439, 508, 601, 602, 630], - 'Matériel et électronique': [ + u'Bureautique et rédaction': [244, 409, 439, 508, 601, 602, 630], + u'Matériel et électronique': [ 253, 255, 264, 279, 343, 349, 364, 365, 371, 374, 428, 429, 507, 599, 613, 640, 686, 749, 757, 895, 917, 1116], - 'Programmation et algorithmique': [5, 28, 30, 39, 43, 54, 56, 60, 61, 65, 66, 67, 78, 96, 100, 152, 158, 159, - 160, 164, 175, 209, 223, 247, 248, 260, 262, 272, 274, 281, 292, 309, 312, - 315, 325, 331, 334, 427, 460, 461, 476, 484, 496, 528, 531, 553, 558, 574, - 582, 591, 597, 609, 612, 621, 624, 634, 644, 645, 646, 674, 681, 685, 706, - 723, 755, 799, 839, 870, 884, 912, 945, 954, 962], - 'Site Web': [57, 193, 232, 241, 246, 248, 292, 295, 312, 344, 351, 352, 358, 411, 446, 449, 449, 527, 574, 591, - 597, 598, 599, 612, 620, 622, 925, 945], - 'Systèmes d’exploitation': [37, 39, 97, 100, 130, 143, 158, 268, 317, 357, 507, 607, 624, 609, 662, 683], - 'Autres (informatique)': [4, 12, 88, 193, 245, 250, 297, 299, 321, 323, 324, 351, 379, 415, 723, 730, 925], + u'Programmation et algorithmique': [5, 28, 30, 39, 43, 54, 56, 60, 61, 65, 66, 67, 78, 96, 100, 152, 158, 159, + 160, 164, 175, 209, 223, 247, 248, 260, 262, 272, 274, 281, 292, 309, 312, + 315, 325, 331, 334, 427, 460, 461, 476, 484, 496, 528, 531, 553, 558, 574, + 582, 591, 597, 609, 612, 621, 624, 634, 644, 645, 646, 674, 681, 685, 706, + 723, 755, 799, 839, 870, 884, 912, 945, 954, 962], + u'Site Web': [57, 193, 232, 241, 246, 248, 292, 295, 312, 344, 351, 352, 358, 411, 446, 449, 449, 527, 574, 591, + 597, 598, 599, 612, 620, 622, 925, 945], + u'Systèmes d\'exploitation': [37, 39, 97, 100, 130, 143, 158, 268, 317, 357, 507, 607, 624, 609, 662, 683], + u'Autres (informatique)': [4, 12, 88, 193, 245, 250, 297, 299, 321, 323, 324, 351, 379, 415, 723, 730, 925], # Sciences de la nature - 'Astronomie': [63, 85, 102, 105, 378, 408], - 'Géologie et géographie physique': [169, 378, 403, 404, 405, 408, 526], - 'Biologie': [105, 148, 157, 223, 410, 451, 493], - 'Physique': [74, 148, 164, 279, 381, 428, 614, 895, 1052], - 'Chimie': [73, 166, 253, 569], - 'Mathématiques': [27, 43, 54, 65, 66, 67, 160, 244, 281, 329, 484, 528, 596, 676, 735, 803, 810, 829, 1184], - 'Autres (sciences de la nature)': [44], + u'Astronomie': [63, 85, 102, 105, 378, 408], + u'Géologie et géographie physique': [169, 378, 403, 404, 405, 408, 526], + u'Biologie': [105, 148, 157, 223, 410, 451, 493], + u'Physique': [74, 148, 164, 279, 381, 428, 614, 895, 1052], + u'Chimie': [73, 166, 253, 569], + u'Mathématiques': [27, 43, 54, 65, 66, 67, 160, 244, 281, 329, 484, 528, 596, 676, 735, 803, 810, 829, 1184], + u'Autres (sciences de la nature)': [44], # Sciences humaines et sociales - 'Droit': [59, 261, 444], - 'Histoire': [12, 54, 65, 66, 155, 183, 381, 614, 676], - 'Langues': [155, 162, 376, 452, 748], - 'Psychologie': [4, 163, 171, 305, 352, 410, 421, 479, 488, 604, 793], - 'Économie': [197, 500], - 'Autres (sciences humaines et sociales)': [127], + u'Droit': [59, 261, 444], + u'Histoire': [12, 54, 65, 66, 155, 183, 381, 614, 676], + u'Langues': [155, 162, 376, 452, 748], + u'Psychologie': [4, 163, 171, 305, 352, 410, 421, 479, 488, 604, 793], + u'Économie': [197, 500], + u'Autres (sciences humaines et sociales)': [127], # Autres - 'Arts, graphisme et multimédia': [151, 153, 212, 251, 334, 599, 626, 655, 656, 671, 706, 751, 913], - 'Communication et management': [305, 341, 391], - 'Zeste de Savoir': [1, 8, 9, 11, 13, 14, 15, 20, 22, 36, 38, 40, 48, 49, 52, 59, 64, 71, 72, 77, 82, 83, 86, 90, - 93, 99, 108, 115, 137, 138, 142, 145, 173, 174, 185, 194, 195, 196, 198, 206, 216, 222, 244, - 249, 261, 877, 978, 1002, 1120, 1162, ], - 'Autres': [11, 13, 14, 15, 52, 69, 90, 95, 103, 104, 142, 173, 196, 195, 936, 950, 1139], + u'Arts, graphisme et multimédia': [151, 153, 212, 251, 334, 599, 626, 655, 656, 671, 706, 751, 913], + u'Communication et management': [305, 341, 391], + u'Zeste de Savoir': [1, 8, 9, 11, 13, 14, 15, 20, 22, 36, 38, 40, 48, 49, 52, 59, 64, 71, 72, 77, 82, 83, 86, + 90, 93, 99, 108, 115, 137, 138, 142, 145, 173, 174, 185, 194, 195, 196, 198, 206, 216, 222, + 244, 249, 261, 877, 978, 1002, 1120, 1162, 1062], + u'Autres': [11, 13, 14, 15, 52, 69, 90, 95, 103, 104, 142, 173, 196, 195, 936, 950, 1139, 1214], } - contents_pk = [item['pk'] for item in PublishableContent.objects.values('pk')] + contents_pk = [item['pk'] for item in PublishableContent.objects.values(u'pk')] for subcat, cts in contents.items(): for ct in cts: try: @@ -220,28 +226,34 @@ def migrate_zds(): except ValueError: # contents with more than one category pass - print('[ZEP-25] : New category "{}" for content "{}"'.format(subcategory, content)) + print(u'[ZEP-25] : New category "{}" for content "{}"'.format(subcategory, content)) sucess += 1 except PublishableContent.DoesNotExist: - print('[ZEP-25][WARNING] : Content with pk "{}" is not in list, it should not happend in production' + print(u'[ZEP-25][WARNING] : Content with pk "{}" is not in list, it should not happend in production' .format(ct)) fail += 1 # alert for content not in list for pk in contents_pk: - content = PublishableContent.objects.get(pk=pk) - print('[ZEP-25][WARNING] : Content "{}" (pk = {}) is not migrate (not in list), please check it'.format(content, - pk)) - missing += 1 + try: + content = PublishedContent.objects.get(pk=pk) + # only online content + if content: + print(u'[ZEP-25][WARNING] : Content "{}" (pk = {}) is not migrate (not in list), please check it' + .format(content, pk)) + missing += 1 + except PublishedContent.DoesNotExist: + # content is not published at this moment (removed, beta version...) + pass # migration details - print('\n================================================================================\n') - print('{} content(s) migrated with succes'.format(sucess)) - print('{} content(s) failed'.format(fail)) - print('{} content(s) unmigrated'.format(missing)) + print(u'\n================================================================================\n') + print(u'{} online content(s) migrated with succes'.format(sucess)) + print(u'{} online content(s) failed'.format(fail)) + print(u'{} online content(s) unmigrated'.format(missing)) if fail != 0 or missing != 0: - print('\nPLEASE CHECKS LOGS.') - print('\n================================================================================\n') + print(u'\nPLEASE CHECKS LOGS (WARNINGS).') + print(u'\n================================================================================\n') @transaction.atomic @@ -265,7 +277,7 @@ def handle(self, *args, **options): elif args[0] == 'prod': migrate_zds() else: - print('Unknow option.') + print(u'Unknow option.') print(self.help) else: categories_to_tags()