def load_categories_content(cli, size, fake, *_, **__): """ Load categories, subcategories and licenses for tutorials and articles """ # Load a few licenses, while avoiding creating duplicates of what may have been loaded before lics = ["Tous droits réservés", "CC BY"] for lic in lics: if Licence.objects.filter(code=lic).count() == 0: licence = Licence(code=lic, title=lic, description="") licence.save() cli.stdout.write("Note : ajout de la licence `{}`".format(lic)) categories = [] sub_categories = [] nb_categories = size * 5 nb_sub_categories = size * 10 cli.stdout.write( "Nombres de catégories de contenus à créer : {}".format(nb_categories)) cli.stdout.write( "Nombres de sous-catégories de contenus à créer : {}".format( nb_sub_categories)) tps1 = time.time() for i in range(0, nb_categories): ttl = str(i) + " " + fake.job() cat = TCategory(title=ttl, description=fake.sentence(nb_words=15, variable_nb_words=True), slug=old_slugify(ttl)) cat.save() categories.append(cat) sys.stdout.write(" Cat. {}/{} \r".format(i + 1, nb_categories)) sys.stdout.flush() for i in range(0, nb_sub_categories): with contextlib.suppress(IntegrityError): ttl = str(i * 10) + str(i) + " " + fake.word() subcat = SubCategory(title=ttl, subtitle=fake.sentence( nb_words=5, variable_nb_words=True), slug=old_slugify(ttl)) subcat.save() sub_categories.append(subcat) sys.stdout.write(" SubCat. {}/{} \r".format(i + 1, nb_sub_categories)) sys.stdout.flush() for i in range(0, nb_sub_categories): with contextlib.suppress(IntegrityError): catsubcat = CategorySubCategory(category=categories[i % nb_categories], subcategory=sub_categories[i], is_main=True) catsubcat.save() sys.stdout.write(" CatSubCat. {}/{} \r".format( i + 1, nb_sub_categories)) sys.stdout.flush() tps2 = time.time() cli.stdout.write("\nFait en {} sec".format(tps2 - tps1))
def slugify_raise_on_invalid(title, use_old_slugify=False): """use uuslug to generate a slug but if the title is incorrect (only special chars or slug is empty), an exception is raised. :param title: to be slugified title :type title: str :param use_old_slugify: use the function `slugify()` defined in zds.utils instead of the one in uuslug. Usefull for retro-compatibility with the old article/tutorial module, SHOULD NOT be used for the new one ! :type use_old_slugify: bool :raise InvalidSlugError: on incorrect slug: :return: the slugified title :rtype: str """ if not isinstance(title, basestring): raise InvalidSlugError('', source=title) if not use_old_slugify: slug = slugify(title) else: slug = old_slugify(title) if not check_slug(slug): raise InvalidSlugError(slug, source=title) return slug
class HelpWritingFactory(factory.DjangoModelFactory): class Meta: model = HelpWriting title = factory.Sequence("titre de l'image {0}".format) slug = factory.LazyAttribute(lambda o: "{0}".format(old_slugify(o.title))) tablelabel = factory.LazyAttribute(lambda n: "Besoin de " + n.title) @classmethod def _prepare(cls, create, **kwargs): help_writing = super(HelpWritingFactory, cls)._prepare(create, **kwargs) image_path = kwargs.pop("image_path", None) fixture_image_path = kwargs.pop("fixture_image_path", None) if fixture_image_path is not None: image_path = join(settings.BASE_DIR, "fixtures", fixture_image_path) if image_path is not None: copyfile(image_path, settings.MEDIA_ROOT / basename(image_path)) help_writing.image = basename(image_path) help_writing.save() return help_writing @classmethod def _create(cls, target_class, *args, **kwargs): kwargs.pop("image_path", None) kwargs.pop("fixture_image_path", None) return super(HelpWritingFactory, cls)._create(target_class, *args, **kwargs)
def test_notification_read(self): """ When we post on a topic, a notification is created for each subscriber. We can read a notification when we display the list of messages of the said topic. """ topic1 = TopicFactory(forum=self.forum11, author=self.user2) PostFactory(topic=topic1, author=self.user2, position=1) result = self.client.post( reverse("post-new") + f"?sujet={topic1.pk}", { "last_post": topic1.last_message.pk, "text": "C'est tout simplement l'histoire de la ville de Paris que je voudrais vous conter ", }, follow=False, ) self.assertEqual(result.status_code, 302) notification = Notification.objects.get(subscription__user=self.user2) self.assertEqual(notification.is_read, False) self.client.logout() self.client.force_login(self.user2) result = self.client.get(reverse( "topic-posts-list", args=[topic1.pk, old_slugify(topic1.title)]), follow=True) self.assertEqual(result.status_code, 200) notification = Notification.objects.get(subscription__user=self.user2) self.assertEqual(notification.is_read, True)
def slug(self): """ PrivateTopic doesn't have a slug attribute of a private topic. To be compatible with older private topic, the slug is always re-calculated when we need one. :return: title slugify. """ return old_slugify(self.title)
def slugify_raise_on_invalid(title, use_old_slugify=False): """ use uuslug to generate a slug but if the title is incorrect (only special chars or slug is empty), an exception is raised. :param title: to be slugified title :type title: str :param use_old_slugify: use the function `slugify()` defined in zds.utils instead of the one in uuslug. Usefull \ for retro-compatibility with the old article/tutorial module, SHOULD NOT be used for the new one ! :type use_old_slugify: bool :raise InvalidSlugError: on incorrect slug :return: the slugified title :rtype: str """ if not isinstance(title, str): raise InvalidSlugError('', source=title) if not use_old_slugify: slug = slugify(title) else: slug = old_slugify(title) if not check_slug(slug): raise InvalidSlugError(slug, source=title) return slug
def get(self, request, *args, **kwargs): self.object = self.get_object() if not self.object.forum.can_read(request.user): raise PermissionDenied if not self.kwargs.get("topic_slug") == old_slugify(self.object.title): return redirect(self.object.get_absolute_url()) return super().get(request, *args, **kwargs)
def save(self, *args, **kwargs): self.title = self.title.strip() if not self.title or not old_slugify(self.title.replace("-", "")): raise ValueError('Tag "{}" is not correct'.format(self.title)) self.title = smart_text(self.title).lower() self.slug = uuslug(self.title, instance=self, max_length=Tag._meta.get_field("slug").max_length) super(Tag, self).save(*args, **kwargs)
class GalleryFactory(factory.DjangoModelFactory): class Meta: model = Gallery title = factory.Sequence("titre de la gallerie {0}".format) subtitle = factory.Sequence("Sous-titre de la gallerie {0}".format) slug = factory.LazyAttribute(lambda o: "{0}".format(old_slugify(o.title))) @classmethod def _prepare(cls, create, **kwargs): gal = super(GalleryFactory, cls)._prepare(create, **kwargs) with contextlib.suppress(OSError): gal.get_gallery_path().mkdir(parents=True) return gal
class ImageFactory(factory.DjangoModelFactory): class Meta: model = Image title = factory.Sequence("titre de l'image {0}".format) slug = factory.LazyAttribute(lambda o: "{0}".format(old_slugify(o.title))) legend = factory.Sequence("legende de l'image {0}".format) physical = factory.django.ImageField(color="blue") @classmethod def _prepare(cls, create, **kwargs): gallery = kwargs.pop("gallery", None) if gallery is not None: image = super(ImageFactory, cls)._prepare(create, gallery=gallery, **kwargs) else: image = None return image
class ImageFactory(factory.django.DjangoModelFactory): class Meta: model = Image title = factory.Sequence("titre de l'image {}".format) slug = factory.LazyAttribute(lambda o: "{}".format(old_slugify(o.title))) legend = factory.Sequence("legende de l'image {}".format) physical = factory.django.ImageField(color="blue") @classmethod def _generate(cls, create, attrs): # Only creates the Image if a Gallery is associated gallery = attrs.get("gallery", None) if gallery is not None: image = super()._generate(create, attrs) else: image = None return image
class HelpWritingFactory(factory.django.DjangoModelFactory): """ Factory that creates a HelpWriting. """ class Meta: model = HelpWriting title = factory.Sequence("titre de l'image {}".format) slug = factory.LazyAttribute(lambda o: "{}".format(old_slugify(o.title))) tablelabel = factory.LazyAttribute(lambda n: "Besoin de " + n.title) @classmethod def _generate(cls, create, attrs): # These parameters are only used inside _generate() and won't be saved in the database, # which is why we use attrs.pop() (they are removed from attrs). image_path = attrs.pop("image_path", None) fixture_image_path = attrs.pop("fixture_image_path", None) help_writing = super()._generate(create, attrs) if fixture_image_path is not None: image_path = join(settings.BASE_DIR, "fixtures", fixture_image_path) if image_path is not None: copyfile(image_path, settings.MEDIA_ROOT / basename(image_path)) help_writing.image = basename(image_path) help_writing.save() return help_writing @classmethod def _create(cls, target_class, *args, **kwargs): kwargs.pop("image_path", None) kwargs.pop("fixture_image_path", None) return super()._create(target_class, *args, **kwargs)
def build_html_chapter_file(published_object, versioned_object, working_dir, root_dir, image_handler): """ Parses the full html file, extracts the ``<hX>`` tags and splits their content into new files. Yields all the produced files. :param root_dir: the root directory into which dump the ebook :type root_dir: pathlib.Path :param working_dir: :type working_dir: pathlib.Path :param versioned_object: the object representing the public version in git file system :type versioned_object: zds.tutorialv2.models.models_versioned.VersionedContent :param published_object: the published content as saved in database :type published_object: zds.tutorialv2.models.models_database.PublishedContent :type image_handler: ImageHandling :return: a generator of tuples composed as ``[splitted_html_file_relative_path, chapter-identifier, chapter-title]`` """ DirTuple = namedtuple("DirTuple", ["absolute", "relative"]) img_dir = working_dir.parent / "images" path_to_title_dict = publish_container( published_object, str(working_dir), versioned_object, template="tutorialv2/export/ebook/chapter.html", file_ext="xhtml", image_callback=image_handler.handle_images, image_directory=DirTuple(str(img_dir.absolute()), str(img_dir.relative_to(root_dir))), relative=".", intro_ccl_template="tutorialv2/export/ebook/introduction.html", ) for container_path, title in path_to_title_dict.items(): # TODO: check if a function exists in the std lib to get rid of `root_dir + '/'` yield container_path.replace( str(root_dir.absolute()) + "/", ""), "chapter-" + old_slugify(title), title
def save(self, *args, **kwargs): self.slug = old_slugify(self.title) super(HelpWriting, self).save(*args, **kwargs)
def slug(self): return old_slugify(self.title)
def save(self, *args, **kwargs): self.slug = old_slugify(self.title) super().save(*args, **kwargs)