From b485f74c2cfd3778c94599dd231428162085c279 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Fri, 23 Dec 2022 19:12:09 +0100 Subject: [PATCH 01/11] =?UTF-8?q?Permet=20d'=C3=A9crire=20des=20billets=20?= =?UTF-8?q?ou=20articles=20avec=20une=20structure=20de=20tutoriel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zds/tutorialv2/models/__init__.py | 7 -- zds/tutorialv2/models/versioned.py | 29 +++---- zds/tutorialv2/tests/tests_opinion_views.py | 8 -- zds/tutorialv2/tests/tests_routes.py | 96 +++++++++++++++++++++ zds/tutorialv2/urls/urls_articles.py | 25 ++++-- zds/tutorialv2/urls/urls_opinions.py | 25 ++++-- 6 files changed, 146 insertions(+), 44 deletions(-) create mode 100644 zds/tutorialv2/tests/tests_routes.py diff --git a/zds/tutorialv2/models/__init__.py b/zds/tutorialv2/models/__init__.py index b636226aa8..e96c506d1f 100644 --- a/zds/tutorialv2/models/__init__.py +++ b/zds/tutorialv2/models/__init__.py @@ -8,7 +8,6 @@ # verbose_name_plural User-friendly pluralized type name # category_name User-friendly category name which contains this content # requires_validation Boolean; whether this content has to be validated before publication - # single_container Boolean; True if the content is a single container # beta Boolean; True if the content can be in beta { "name": "TUTORIAL", @@ -16,7 +15,6 @@ "verbose_name_plural": "tutoriels", "category_name": "tutoriel", "requires_validation": True, - "single_container": False, "beta": True, }, { @@ -25,7 +23,6 @@ "verbose_name_plural": "articles", "category_name": "article", "requires_validation": True, - "single_container": True, "beta": True, }, { @@ -34,7 +31,6 @@ "verbose_name_plural": "billets", "category_name": "tribune", "requires_validation": False, - "single_container": True, "beta": False, }, ) @@ -49,9 +45,6 @@ # a list of contents which have to be validated before publication CONTENT_TYPES_REQUIRING_VALIDATION = [content["name"] for content in CONTENT_TYPES if content["requires_validation"]] -# a list of contents which have one big container containing at least one small container -SINGLE_CONTAINER_CONTENT_TYPES = [content["name"] for content in CONTENT_TYPES if content["single_container"]] - # a list of contents which can be in beta CONTENT_TYPES_BETA = [content["name"] for content in CONTENT_TYPES if content["beta"]] diff --git a/zds/tutorialv2/models/versioned.py b/zds/tutorialv2/models/versioned.py index b43753a1f7..faf8331b4b 100644 --- a/zds/tutorialv2/models/versioned.py +++ b/zds/tutorialv2/models/versioned.py @@ -1,6 +1,7 @@ import contextlib import copy from pathlib import Path +from typing import List from zds import json_handler from git import Repo @@ -15,7 +16,7 @@ from django.template.loader import render_to_string from zds.tutorialv2.models.mixins import TemplatableContentModelMixin -from zds.tutorialv2.models import SINGLE_CONTAINER_CONTENT_TYPES, CONTENT_TYPES_REQUIRING_VALIDATION +from zds.tutorialv2.models import CONTENT_TYPES_REQUIRING_VALIDATION from zds.tutorialv2.utils import default_slug_pool, export_content, get_commit_author, InvalidOperationError from zds.tutorialv2.utils import get_blob from zds.utils.validators import InvalidSlugError, check_slug @@ -265,8 +266,7 @@ def can_add_container(self): """ if not self.has_extracts(): if self.get_tree_depth() < settings.ZDS_APP["content"]["max_tree_depth"] - 1: - if not self.top_container().type in SINGLE_CONTAINER_CONTENT_TYPES: - return True + return True return False def can_add_extract(self): @@ -1331,21 +1331,16 @@ def get_prod_path(self, relative=False, file_ext="html"): return path - def get_list_of_chapters(self): - """ - :return: a list of chapters (Container which contains Extracts) in the reading order - :rtype: list[Container] - """ + def get_list_of_chapters(self) -> list[Container]: continuous_list = [] - if self.type not in SINGLE_CONTAINER_CONTENT_TYPES: # cannot be paginated - if len(self.children) != 0 and isinstance(self.children[0], Container): # children must be Containers! - for child in self.children: - if len(child.children) != 0: - if isinstance(child.children[0], Extract): - continuous_list.append(child) # it contains Extract, this is a chapter, so paginated - else: # Container is a part - for sub_child in child.children: - continuous_list.append(sub_child) # even if empty `sub_child.childreen`, it's chapter + if len(self.children) != 0 and isinstance(self.children[0], Container): # children must be Containers! + for child in self.children: + if len(child.children) != 0: + if isinstance(child.children[0], Extract): + continuous_list.append(child) # it contains Extract, this is a chapter, so paginated + else: # Container is a part + for sub_child in child.children: + continuous_list.append(sub_child) # even if empty `sub_child.childreen`, it's chapter return continuous_list def get_json(self): diff --git a/zds/tutorialv2/tests/tests_opinion_views.py b/zds/tutorialv2/tests/tests_opinion_views.py index 418ca9ada4..56b2a6194d 100644 --- a/zds/tutorialv2/tests/tests_opinion_views.py +++ b/zds/tutorialv2/tests/tests_opinion_views.py @@ -177,14 +177,6 @@ def test_accessible_ui_for_author(self): self.assertNotContains(resp, "{}?subcategory=".format(reverse("publication:list"))) self.assertContains(resp, "{}?category=".format(reverse("opinion:list"))) - def test_no_help_for_tribune(self): - self.client.force_login(self.user_author) - - def test_help_for_article(self): - self.client.force_login(self.user_author) - resp = self.client.get(reverse("content:create-content", kwargs={"created_content_type": "ARTICLE"})) - self.assertEqual(200, resp.status_code) - def test_opinion_publication_staff(self): """ Test the publication of PublishableContent where type is OPINION (with staff). diff --git a/zds/tutorialv2/tests/tests_routes.py b/zds/tutorialv2/tests/tests_routes.py new file mode 100644 index 0000000000..31db6c924d --- /dev/null +++ b/zds/tutorialv2/tests/tests_routes.py @@ -0,0 +1,96 @@ +from django.test import TestCase +from django.urls import reverse + +from zds.tutorialv2.models.database import PublishableContent +from zds.tutorialv2.publication_utils import publish_content +from zds.tutorialv2.tests import override_for_contents, TutorialTestMixin +from zds.tutorialv2.tests.factories import PublishableContentFactory, ContainerFactory + + +@override_for_contents() +class BasicRouteTests(TestCase, TutorialTestMixin): + def setUp(self): + self.build_content(self.content_type) + self.mock_publication_process(self.content) + + def build_content(self, type): + self.content = PublishableContentFactory() + self.content.type = type + self.content.save() + content_versioned = self.content.load_version() + self.container = ContainerFactory(parent=content_versioned, db_object=self.content) + self.subcontainer = ContainerFactory(parent=self.container, db_object=self.content) + + def assert_can_be_reached(self, route, route_args): + url = reverse(route, kwargs=route_args) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + + def mock_publication_process(self, content: PublishableContent): + published = publish_content(content, content.load_version()) + content.sha_public = content.sha_draft + content.public_version = published + content.save() + + +class OpinionDisplayRoutesTests(BasicRouteTests): + content_type = "OPINION" + + def test_view(self): + route = "opinion:view" + route_args = { + "pk": self.content.pk, + "slug": self.content.slug, + } + self.assert_can_be_reached(route, route_args) + + def test_view_container_one_level_deep(self): + route = "opinion:view-container" + route_args = { + "pk": self.content.pk, + "slug": self.content.slug, + "container_slug": self.container.slug, + } + self.assert_can_be_reached(route, route_args) + + def test_view_container_two_level_deep(self): + route = "opinion:view-container" + route_args = { + "pk": self.content.pk, + "slug": self.content.slug, + "parent_container_slug": self.container.slug, + "container_slug": self.subcontainer.slug, + } + self.assert_can_be_reached(route, route_args) + + +@override_for_contents() +class ArticlesDisplayRoutesTests(BasicRouteTests): + content_type = "ARTICLE" + + def test_view(self): + route = "article:view" + route_args = { + "pk": self.content.pk, + "slug": self.content.slug, + } + self.assert_can_be_reached(route, route_args) + + def test_view_container_one_level_deep(self): + route = "article:view-container" + route_args = { + "pk": self.content.pk, + "slug": self.content.slug, + "container_slug": self.container.slug, + } + self.assert_can_be_reached(route, route_args) + + def test_view_container_two_level_deep(self): + route = "article:view-container" + route_args = { + "pk": self.content.pk, + "slug": self.content.slug, + "parent_container_slug": self.container.slug, + "container_slug": self.subcontainer.slug, + } + self.assert_can_be_reached(route, route_args) diff --git a/zds/tutorialv2/urls/urls_articles.py b/zds/tutorialv2/urls/urls_articles.py index 98afa89715..83d1426539 100644 --- a/zds/tutorialv2/urls/urls_articles.py +++ b/zds/tutorialv2/urls/urls_articles.py @@ -4,22 +4,33 @@ from zds.tutorialv2.views.contributors import ContentOfContributors from zds.tutorialv2.views.lists import TagsListView, ContentOfAuthor from zds.tutorialv2.views.download_online import DownloadOnlineArticle -from zds.tutorialv2.views.display import ArticleOnlineView +from zds.tutorialv2.views.display import ArticleOnlineView, ContainerOnlineView from zds.tutorialv2.feeds import LastArticlesFeedRSS, LastArticlesFeedATOM -urlpatterns = [ - # Flux +feed_patterns = [ path("flux/rss/", LastArticlesFeedRSS(), name="feed-rss"), path("flux/atom/", LastArticlesFeedATOM(), name="feed-atom"), - # View +] + +display_patterns = [ path("//", ArticleOnlineView.as_view(), name="view"), - # Downloads + path( + "////", + ContainerOnlineView.as_view(), + name="view-container", + ), + path("///", ContainerOnlineView.as_view(), name="view-container"), +] + +download_patterns = [ path("md//.md", DownloadOnlineArticle.as_view(requested_file="md"), name="download-md"), path("pdf//.pdf", DownloadOnlineArticle.as_view(requested_file="pdf"), name="download-pdf"), path("tex//.tex", DownloadOnlineArticle.as_view(requested_file="tex"), name="download-tex"), path("epub//.epub", DownloadOnlineArticle.as_view(requested_file="epub"), name="download-epub"), path("zip//.zip", DownloadOnlineArticle.as_view(requested_file="zip"), name="download-zip"), - # Listing +] + +listing_patterns = [ path("", RedirectView.as_view(pattern_name="publication:list", permanent=True)), re_path(r"tags/*", TagsListView.as_view(displayed_types=["ARTICLE"]), name="tags"), path( @@ -33,3 +44,5 @@ name="find-contributions-article", ), ] + +urlpatterns = feed_patterns + display_patterns + download_patterns + listing_patterns diff --git a/zds/tutorialv2/urls/urls_opinions.py b/zds/tutorialv2/urls/urls_opinions.py index f5d80d52a9..9c625b473b 100644 --- a/zds/tutorialv2/urls/urls_opinions.py +++ b/zds/tutorialv2/urls/urls_opinions.py @@ -3,21 +3,32 @@ from zds.tutorialv2.feeds import LastOpinionsFeedRSS, LastOpinionsFeedATOM from zds.tutorialv2.views.lists import ListOpinions, ContentOfAuthor from zds.tutorialv2.views.download_online import DownloadOnlineOpinion -from zds.tutorialv2.views.display import OpinionOnlineView +from zds.tutorialv2.views.display import OpinionOnlineView, ContainerOnlineView -urlpatterns = [ - # Flux +feed_patterns = [ path("flux/rss/", LastOpinionsFeedRSS(), name="feed-rss"), path("flux/atom/", LastOpinionsFeedATOM(), name="feed-atom"), - # View +] + +display_patterns = [ path("//", OpinionOnlineView.as_view(), name="view"), - # downloads: + path( + "////", + ContainerOnlineView.as_view(), + name="view-container", + ), + path("///", ContainerOnlineView.as_view(), name="view-container"), +] + +download_patterns = [ path("md//.md", DownloadOnlineOpinion.as_view(requested_file="md"), name="download-md"), path("pdf//.pdf", DownloadOnlineOpinion.as_view(requested_file="pdf"), name="download-pdf"), path("epub//.epub", DownloadOnlineOpinion.as_view(requested_file="epub"), name="download-epub"), path("zip//.zip", DownloadOnlineOpinion.as_view(requested_file="zip"), name="download-zip"), path("tex//.tex", DownloadOnlineOpinion.as_view(requested_file="tex"), name="download-tex"), - # Listing +] + +listing_patterns = [ path("", ListOpinions.as_view(), name="list"), path( "voir//", @@ -25,3 +36,5 @@ name="find-opinion", ), ] + +urlpatterns = feed_patterns + display_patterns + download_patterns + listing_patterns From 82b59c23fb7f12ab6ba1fbd5c3fbbc84d4f54b16 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sat, 9 Dec 2023 19:06:08 +0100 Subject: [PATCH 02/11] Supprime un import inutile --- zds/tutorialv2/models/versioned.py | 1 - 1 file changed, 1 deletion(-) diff --git a/zds/tutorialv2/models/versioned.py b/zds/tutorialv2/models/versioned.py index faf8331b4b..28c8c3f662 100644 --- a/zds/tutorialv2/models/versioned.py +++ b/zds/tutorialv2/models/versioned.py @@ -1,7 +1,6 @@ import contextlib import copy from pathlib import Path -from typing import List from zds import json_handler from git import Repo From a2bbd27aa844406c4615f62d480b1479b5dec5a8 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sat, 9 Dec 2023 19:12:07 +0100 Subject: [PATCH 03/11] Refactorise les patterns d'URL pour les tutoriels --- zds/tutorialv2/urls/urls_tutorials.py | 34 +++++++++++++++++---------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/zds/tutorialv2/urls/urls_tutorials.py b/zds/tutorialv2/urls/urls_tutorials.py index 77ffa78dc8..76f9fc46a1 100644 --- a/zds/tutorialv2/urls/urls_tutorials.py +++ b/zds/tutorialv2/urls/urls_tutorials.py @@ -8,17 +8,12 @@ from zds.tutorialv2.views.redirect import RedirectContentSEO, RedirectOldBetaTuto from zds.tutorialv2.feeds import LastTutorialsFeedRSS, LastTutorialsFeedATOM - -urlpatterns = [ - # flux +feed_patterns = [ path("flux/rss/", LastTutorialsFeedRSS(), name="feed-rss"), path("flux/atom/", LastTutorialsFeedATOM(), name="feed-atom"), - # view - path( - "//////", - RedirectContentSEO.as_view(), - name="redirect_old_tuto", - ), +] + +display_patterns = [ path( "////", ContainerOnlineView.as_view(), @@ -26,15 +21,17 @@ ), path("///", ContainerOnlineView.as_view(), name="view-container"), path("//", TutorialOnlineView.as_view(), name="view"), - # downloads: +] + +download_patterns = [ path("md//.md", DownloadOnlineTutorial.as_view(requested_file="md"), name="download-md"), path("pdf//.pdf", DownloadOnlineTutorial.as_view(requested_file="pdf"), name="download-pdf"), path("epub//.epub", DownloadOnlineTutorial.as_view(requested_file="epub"), name="download-epub"), path("zip//.zip", DownloadOnlineTutorial.as_view(requested_file="zip"), name="download-zip"), path("tex//.tex", DownloadOnlineTutorial.as_view(requested_file="tex"), name="download-tex"), - # Old beta url compatibility - path("beta///", RedirectOldBetaTuto.as_view(), name="old-beta-url"), - # Listing +] + +listing_patterns = [ path("", RedirectView.as_view(pattern_name="publication:list", permanent=True)), path("tags/", TagsListView.as_view(displayed_types=["TUTORIAL"]), name="tags"), path( @@ -48,3 +45,14 @@ name="find-contributions-tutorial", ), ] + +redirect_patterns = [ + path( + "//////", + RedirectContentSEO.as_view(), + name="redirect_old_tuto", + ), + path("beta///", RedirectOldBetaTuto.as_view(), name="old-beta-url"), +] + +urlpatterns = feed_patterns + display_patterns + download_patterns + listing_patterns + redirect_patterns From 6846d4931ce39312d75750d65e17c7c46ee01395 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:50:45 +0200 Subject: [PATCH 04/11] Fix can_add_container --- zds/tutorialv2/models/versioned.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/zds/tutorialv2/models/versioned.py b/zds/tutorialv2/models/versioned.py index 28c8c3f662..5fc579a21e 100644 --- a/zds/tutorialv2/models/versioned.py +++ b/zds/tutorialv2/models/versioned.py @@ -258,15 +258,14 @@ def long_slug(self): long_slug = self.parent.long_slug() + "__" return long_slug + self.slug - def can_add_container(self): + def can_add_container(self) -> bool: """ - :return: ``True`` if this container accepts child containers, ``False`` otherwise - :rtype: bool + Return `True` if adding child containers is allowed. + Adding subcontainers is forbidden: + * if the container already has extracts as children, + * or if the limit of nested containers has been reached. """ - if not self.has_extracts(): - if self.get_tree_depth() < settings.ZDS_APP["content"]["max_tree_depth"] - 1: - return True - return False + return not self.has_extracts() and self.get_tree_depth() < settings.ZDS_APP["content"]["max_tree_depth"] - 1 def can_add_extract(self): """Return ``True`` if this container can contain extracts, i.e doesn't From c069e8d45c292c9d27b316399924b0523ecfb623 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:54:23 +0200 Subject: [PATCH 05/11] Fix get_list_of_chapters --- zds/tutorialv2/models/versioned.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/tutorialv2/models/versioned.py b/zds/tutorialv2/models/versioned.py index 5fc579a21e..1e062eeef2 100644 --- a/zds/tutorialv2/models/versioned.py +++ b/zds/tutorialv2/models/versioned.py @@ -1338,7 +1338,7 @@ def get_list_of_chapters(self) -> list[Container]: continuous_list.append(child) # it contains Extract, this is a chapter, so paginated else: # Container is a part for sub_child in child.children: - continuous_list.append(sub_child) # even if empty `sub_child.childreen`, it's chapter + continuous_list.append(sub_child) # even if `sub_child.children` is empty, it's a chapter return continuous_list def get_json(self): From 45f661fd99dc37e7973c62b258ffa49cbd618b65 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:01:23 +0200 Subject: [PATCH 06/11] Fix ligne inutile --- zds/tutorialv2/tests/tests_routes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/zds/tutorialv2/tests/tests_routes.py b/zds/tutorialv2/tests/tests_routes.py index 31db6c924d..5a6bd914a0 100644 --- a/zds/tutorialv2/tests/tests_routes.py +++ b/zds/tutorialv2/tests/tests_routes.py @@ -64,7 +64,6 @@ def test_view_container_two_level_deep(self): self.assert_can_be_reached(route, route_args) -@override_for_contents() class ArticlesDisplayRoutesTests(BasicRouteTests): content_type = "ARTICLE" From e44565bb6186c8b0d2f8438136fbe5cda4976b09 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:05:51 +0200 Subject: [PATCH 07/11] Ajoute les tests de route basiques pour les tutoriels --- zds/tutorialv2/tests/tests_routes.py | 83 +++++++++++----------------- 1 file changed, 33 insertions(+), 50 deletions(-) diff --git a/zds/tutorialv2/tests/tests_routes.py b/zds/tutorialv2/tests/tests_routes.py index 5a6bd914a0..1418a764ce 100644 --- a/zds/tutorialv2/tests/tests_routes.py +++ b/zds/tutorialv2/tests/tests_routes.py @@ -7,11 +7,17 @@ from zds.tutorialv2.tests.factories import PublishableContentFactory, ContainerFactory -@override_for_contents() -class BasicRouteTests(TestCase, TutorialTestMixin): +def mock_publication_process(content: PublishableContent): + published = publish_content(content, content.load_version()) + content.sha_public = content.sha_draft + content.public_version = published + content.save() + + +class BasicRouteTestsMixin(TutorialTestMixin): def setUp(self): self.build_content(self.content_type) - self.mock_publication_process(self.content) + mock_publication_process(self.content) def build_content(self, type): self.content = PublishableContentFactory() @@ -21,75 +27,52 @@ def build_content(self, type): self.container = ContainerFactory(parent=content_versioned, db_object=self.content) self.subcontainer = ContainerFactory(parent=self.container, db_object=self.content) - def assert_can_be_reached(self, route, route_args): - url = reverse(route, kwargs=route_args) - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - - def mock_publication_process(self, content: PublishableContent): - published = publish_content(content, content.load_version()) - content.sha_public = content.sha_draft - content.public_version = published - content.save() - - -class OpinionDisplayRoutesTests(BasicRouteTests): - content_type = "OPINION" - def test_view(self): - route = "opinion:view" route_args = { "pk": self.content.pk, "slug": self.content.slug, } - self.assert_can_be_reached(route, route_args) + self.assert_can_be_reached(self.view_name, route_args) def test_view_container_one_level_deep(self): - route = "opinion:view-container" route_args = { "pk": self.content.pk, "slug": self.content.slug, "container_slug": self.container.slug, } - self.assert_can_be_reached(route, route_args) + self.assert_can_be_reached(self.container_view_name, route_args) def test_view_container_two_level_deep(self): - route = "opinion:view-container" route_args = { "pk": self.content.pk, "slug": self.content.slug, "parent_container_slug": self.container.slug, "container_slug": self.subcontainer.slug, } - self.assert_can_be_reached(route, route_args) + self.assert_can_be_reached(self.container_view_name, route_args) + def assert_can_be_reached(self, route, route_args): + url = reverse(route, kwargs=route_args) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) -class ArticlesDisplayRoutesTests(BasicRouteTests): - content_type = "ARTICLE" - def test_view(self): - route = "article:view" - route_args = { - "pk": self.content.pk, - "slug": self.content.slug, - } - self.assert_can_be_reached(route, route_args) +@override_for_contents() +class OpinionDisplayRoutesTests(BasicRouteTestsMixin, TestCase): + content_type = "OPINION" + view_name = "opinion:view" + container_view_name = "opinion:view-container" - def test_view_container_one_level_deep(self): - route = "article:view-container" - route_args = { - "pk": self.content.pk, - "slug": self.content.slug, - "container_slug": self.container.slug, - } - self.assert_can_be_reached(route, route_args) - def test_view_container_two_level_deep(self): - route = "article:view-container" - route_args = { - "pk": self.content.pk, - "slug": self.content.slug, - "parent_container_slug": self.container.slug, - "container_slug": self.subcontainer.slug, - } - self.assert_can_be_reached(route, route_args) +@override_for_contents() +class ArticlesDisplayRoutesTests(BasicRouteTestsMixin, TestCase): + content_type = "ARTICLE" + view_name = "article:view" + container_view_name = "article:view-container" + + +@override_for_contents() +class TutorialsDisplayRoutesTests(BasicRouteTestsMixin, TestCase): + content_type = "TUTORIAL" + view_name = "tutorial:view" + container_view_name = "tutorial:view-container" From 5e295c7427df36425ca886b36293f5b0da023094 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:56:21 +0200 Subject: [PATCH 08/11] =?UTF-8?q?Mise=20=C3=A0=20jour=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/source/back-end/contents.rst | 39 ++++++++++++-------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/doc/source/back-end/contents.rst b/doc/source/back-end/contents.rst index 0c1d11956e..2d7245a66f 100644 --- a/doc/source/back-end/contents.rst +++ b/doc/source/back-end/contents.rst @@ -1,6 +1,6 @@ -========================= -Les tutoriels et articles -========================= +================================ +Les tutoriels, articles, billets +================================ Vocabulaire et définitions ========================== @@ -50,38 +50,36 @@ Un contenu Un **contenu** est un agencement particulier de conteneurs et d'extraits. Il est décrit par des métadonnées (*metadata*), détaillées -`ici <./contents_manifest.html>`__. Une de ces métadonnées est le type : article -ou tutoriel. Leur visée pédagogique diffère, mais aussi leur structure : un -article ne peut comporter de conteneurs, seulement des extraits, ce qui n'est -pas le cas d'un tutoriel. +`ici <./contents_manifest.html>`__. Une de ces métadonnées est le type : article, tutoriel ou billet. -Les exemples suivants devraient éclairer ces notions. +Techniquement, le type n'a pas d'influencevsur la structure du contenu. On rencontre cependant +des structures typiques selon la longueur du contenu. -Communément appelé « mini-tutoriel » : +Structure typique pour un contenu court : .. sourcecode:: none - + Tutoriel + + Contenu + Section + Section + Section -Communément appelé « moyen-tutoriel » : +Structure typique pour un contenu de taille moyenne : .. sourcecode:: none - + Tutoriel + + Contenu + Partie + Section + Partie + Section + Section -Communément appelé « big-tutoriel » : +Structure typique pour un contenu long : .. sourcecode:: none - + Tutoriel + + Contenu + Partie + Chapitre + Section @@ -93,7 +91,7 @@ Communément appelé « big-tutoriel » : + Section + Section -On peut aussi faire un mélange des conteneurs : +Des structures plus complexes sont possibles, avec des niveaux de conteneurs différents selon les parties : .. sourcecode:: none @@ -107,7 +105,7 @@ On peut aussi faire un mélange des conteneurs : + Chapitre + Section -Mais pas de conteneurs et d'extraits adjacents : +Il n'est pas possible d'avoir à la fois des conteneurs et des extraits au même niveau : .. sourcecode:: none @@ -122,15 +120,6 @@ Mais pas de conteneurs et d'extraits adjacents : + Section + Section /!\ Impossible ! -Pour finir, un article. Même structure qu'un mini-tutoriel, mais vocation -pédagogique différente : - -.. sourcecode:: none - - + Article - + Section - + Section - D'autre part, tout contenu se voit attribuer un identifiant unique sous la forme d'un entier naturel (en anglais : *pk*, pour *primary key*). Cet identifiant apparaît dans les URL, qui sont de la forme From bb4a06b397a9181dd5db23ba947d8de6e7098357 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sun, 8 Sep 2024 12:21:00 +0200 Subject: [PATCH 09/11] Corrige une coquille --- doc/source/back-end/contents.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/back-end/contents.rst b/doc/source/back-end/contents.rst index 2d7245a66f..dd98c3422e 100644 --- a/doc/source/back-end/contents.rst +++ b/doc/source/back-end/contents.rst @@ -52,7 +52,7 @@ Un **contenu** est un agencement particulier de conteneurs et d'extraits. Il est décrit par des métadonnées (*metadata*), détaillées `ici <./contents_manifest.html>`__. Une de ces métadonnées est le type : article, tutoriel ou billet. -Techniquement, le type n'a pas d'influencevsur la structure du contenu. On rencontre cependant +Techniquement, le type n'a pas d'influence sur la structure du contenu. On rencontre cependant des structures typiques selon la longueur du contenu. Structure typique pour un contenu court : From 86d38e505a4d9f4bd2de5c5b9dd671b4a2320aae Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sun, 8 Sep 2024 13:02:43 +0200 Subject: [PATCH 10/11] =?UTF-8?q?Modifie=20la=20g=C3=A9n=C3=A9ration=20des?= =?UTF-8?q?=20fixtures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../management/commands/load_fixtures.py | 67 +++++++++---------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/zds/utils/management/commands/load_fixtures.py b/zds/utils/management/commands/load_fixtures.py index dec45e3df1..0516d98b24 100644 --- a/zds/utils/management/commands/load_fixtures.py +++ b/zds/utils/management/commands/load_fixtures.py @@ -398,7 +398,6 @@ def load_contents(cli, size, fake, _type, *_, **__): nb_avg_containers_in_content = size nb_avg_extracts_in_content = size - is_articles = _type == "ARTICLE" is_tutorials = _type == "TUTORIAL" is_opinion = _type == "OPINION" @@ -411,14 +410,11 @@ def load_contents(cli, size, fake, _type, *_, **__): # small introduction cli.stdout.write(f"À créer: {nb_contents:d} {textual_type}s", ending="") - if is_tutorials: - cli.stdout.write( - " ({:g} petits, {:g} moyens et {:g} grands)".format( - nb_contents * percent_mini, nb_contents * percent_medium, nb_contents * percent_big - ) + cli.stdout.write( + " ({:g} petits, {:g} moyens et {:g} grands)".format( + nb_contents * percent_mini, nb_contents * percent_medium, nb_contents * percent_big ) - else: - cli.stdout.write("") + ) cli.stdout.write( " - {:g} en brouillon".format( @@ -523,15 +519,9 @@ def load_contents(cli, size, fake, _type, *_, **__): versioned = content.load_version() generate_text_for_content( - current_size, - fake, - is_articles, - is_opinion, - nb_avg_containers_in_content, - nb_avg_extracts_in_content, - versioned, + current_size, fake, nb_avg_containers_in_content, nb_avg_extracts_in_content, versioned ) - # add some informations: + # add some information author = users[random.randint(0, nb_users - 1)].user content.authors.add(author) UserGalleryFactory(gallery=content.gallery, mode="W", user=author) @@ -573,18 +563,19 @@ def validate_edited_content(content, fake, nb_staffs, staffs, to_do, versioned): content.save() -def generate_text_for_content( - current_size, fake, is_articles, is_opinion, nb_avg_containers_in_content, nb_avg_extracts_in_content, versioned -): - if current_size == 0 or is_articles or is_opinion: - for _ in range(random.randint(1, nb_avg_extracts_in_content * 2)): - ExtractFactory(container=versioned, title=fake.text(max_nb_chars=60), light=False) +def generate_text_for_content(content_size, fake, nb_avg_containers_in_content, nb_avg_extracts_in_content, versioned): + if content_size == 0: + nb_extracts = random.randint(1, nb_avg_extracts_in_content * 2) + for _ in range(nb_extracts): + extract_title = fake.text(max_nb_chars=60) + ExtractFactory(container=versioned, title=extract_title, light=False) else: - for _ in range(random.randint(1, nb_avg_containers_in_content * 2)): - container = ContainerFactory(parent=versioned, title=fake.text(max_nb_chars=60)) - + nb_containers = random.randint(1, nb_avg_containers_in_content * 2) + for _ in range(nb_containers): + container_title = fake.text(max_nb_chars=60) + container = ContainerFactory(parent=versioned, title=container_title) handle_content_with_chapter_and_parts( - container, current_size, fake, nb_avg_containers_in_content, nb_avg_extracts_in_content + container, content_size, fake, nb_avg_containers_in_content, nb_avg_extracts_in_content ) @@ -599,17 +590,23 @@ def publish_opinion(content, action_flag, versioned): def handle_content_with_chapter_and_parts( - container, current_size, fake, nb_avg_containers_in_content, nb_avg_extracts_in_content + container, size, fake, nb_avg_containers_in_content, nb_avg_extracts_in_content ): - if current_size == 1: # medium size tutorial - for k in range(random.randint(1, nb_avg_extracts_in_content * 2)): - ExtractFactory(container=container, title=fake.text(max_nb_chars=60), light=False) + if size == 1: # medium size tutorial + nb_of_extracts = random.randint(1, nb_avg_extracts_in_content * 2) + for k in range(nb_of_extracts): + extract_title = fake.text(max_nb_chars=60) + ExtractFactory(container=container, title=extract_title, light=False) else: # big-size tutorial - for k in range(random.randint(1, nb_avg_containers_in_content * 2)): - subcontainer = ContainerFactory(parent=container, title=fake.text(max_nb_chars=60)) - - for m in range(random.randint(1, nb_avg_extracts_in_content * 2)): - ExtractFactory(container=subcontainer, title=fake.text(max_nb_chars=60), light=False) + nb_of_containers = random.randint(1, nb_avg_containers_in_content * 2) + for _ in range(nb_of_containers): + subcontainer_title = fake.text(max_nb_chars=60) + subcontainer = ContainerFactory(parent=container, title=subcontainer_title) + + nb_of_extracts = random.randint(1, nb_avg_extracts_in_content * 2) + for _ in range(nb_of_extracts): + extract_title = fake.text(max_nb_chars=60) + ExtractFactory(container=subcontainer, title=extract_title, light=False) ZDSResource = collections.namedtuple("zdsresource", ["name", "description", "callback", "extra_args"]) From 0373dfa806ad6f2322101214ae7c3c49e3453279 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Mon, 9 Sep 2024 19:00:42 +0200 Subject: [PATCH 11/11] Corrige des commentaires --- zds/utils/management/commands/load_fixtures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zds/utils/management/commands/load_fixtures.py b/zds/utils/management/commands/load_fixtures.py index 0516d98b24..bf4c06bfc7 100644 --- a/zds/utils/management/commands/load_fixtures.py +++ b/zds/utils/management/commands/load_fixtures.py @@ -592,12 +592,12 @@ def publish_opinion(content, action_flag, versioned): def handle_content_with_chapter_and_parts( container, size, fake, nb_avg_containers_in_content, nb_avg_extracts_in_content ): - if size == 1: # medium size tutorial + if size == 1: # medium size content nb_of_extracts = random.randint(1, nb_avg_extracts_in_content * 2) for k in range(nb_of_extracts): extract_title = fake.text(max_nb_chars=60) ExtractFactory(container=container, title=extract_title, light=False) - else: # big-size tutorial + else: # big-size content nb_of_containers = random.randint(1, nb_avg_containers_in_content * 2) for _ in range(nb_of_containers): subcontainer_title = fake.text(max_nb_chars=60)