def setUp(self): # don't build PDF to speed up the tests settings.ZDS_APP['content']['build_pdf_when_published'] = False self.staff = StaffProfileFactory().user settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' self.mas = ProfileFactory().user settings.ZDS_APP['member']['bot_account'] = self.mas.username bot = Group(name=settings.ZDS_APP["member"]["bot_group"]) bot.save() self.external = UserFactory( username=settings.ZDS_APP["member"]["external_account"], password="******") self.beta_forum = ForumFactory( pk=settings.ZDS_APP['forum']['beta_forum_id'], category=CategoryFactory(position=1), position_in_category=1 ) # ensure that the forum, for the beta versions, is created self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() self.user_author = ProfileFactory().user self.user_staff = StaffProfileFactory().user self.user_guest = ProfileFactory().user # create an article self.article = PublishableContentFactory(type='ARTICLE') self.article.authors.add(self.user_author) UserGalleryFactory(gallery=self.article.gallery, user=self.user_author, mode='W') self.article.licence = self.licence self.article.subcategory.add(self.subcategory) self.article.save() # fill it with one extract self.article_draft = self.article.load_version() self.extract1 = ExtractFactory(container=self.article_draft, db_object=self.article) # then, publish it ! version = self.article_draft.current_version self.published = publish_content(self.article, self.article_draft, is_major_update=True) self.article.sha_public = version self.article.sha_draft = version self.article.public_version = self.published self.article.save() self.articlefeed = LastArticlesFeedRSS()
def _prepare(cls, create, **kwargs): """create a new PublishableContent and then publish it. """ content = super(PublishedContentFactory, cls)._prepare(create, **kwargs) published = publish_content(content, content.load_version(), True) content.sha_public = content.sha_draft content.public_version = published content.save() return content
def test_publication_and_attributes_consistency(self): pubdate = datetime.now() - timedelta(days=1) article = PublishedContentFactory(type="ARTILCE", author_list=[self.user_author]) public_version = article.public_version public_version.publication_date = pubdate public_version.save() # everything must come from database to have good datetime comparison article = PublishableContent.objects.get(pk=article.pk) article.public_version.load_public_version() old_date = article.public_version.publication_date old_title = article.public_version.title() old_description = article.public_version.description() article.licence = LicenceFactory() article.save() self.assertEqual( self.client.login(username=self.user_author.username, password='******'), True) self.client.post( reverse("content:edit", args=[article.pk, article.slug]), { "title": old_title + "bla", "description": old_description + "bla", "type": "ARTICLE", "licence": article.licence.pk, "subcategory": SubCategoryFactory().pk, "last_hash": article.sha_draft }) article = PublishableContent.objects.prefetch_related( "public_version").get(pk=article.pk) article.public_version.load_public_version() self.assertEqual(old_title, article.public_version.title()) self.assertEqual(old_description, article.public_version.description()) self.assertEqual(old_date, article.public_version.publication_date) publish_content(article, article.load_version(), False) article = PublishableContent.objects.get(pk=article.pk) article.public_version.load_public_version() self.assertEqual(old_date, article.public_version.publication_date) self.assertNotEqual(old_date, article.public_version.update_date)
def migrate_tuto(tutos, title="Exporting mini tuto"): if len(tutos) == 0: return for i in progressbar(xrange(len(tutos)), title, 100): current = tutos[i] if not os.path.exists(current.get_path(False)): sys.stderr.write( 'Invalid physical path to repository « {} », skipping\n'. format(current.get_path(False))) continue exported = PublishableContent() exported.slug = current.slug exported.type = "TUTORIAL" exported.title = current.title exported.sha_draft = current.sha_draft exported.sha_beta = current.sha_beta exported.sha_validation = current.sha_validation exported.licence = current.licence exported.update_date = current.update exported.creation_date = current.create_at exported.description = current.description exported.js_support = current.js_support exported.source = current.source exported.pubdate = current.pubdate exported.save() try: clean_commit = copy_and_clean_repo(current.get_path(False), exported.get_repo_path(False)) except InvalidGitRepositoryError as e: exported.delete() sys.stderr.write( 'Repository in « {} » is invalid, skipping\n'.format(e)) continue if clean_commit: exported.sha_draft = clean_commit # save clean up in old module to avoid any trouble current.sha_draft = clean_commit current.save() exported.gallery = current.gallery exported.image = current.image [ exported.subcategory.add(category) for category in current.subcategory.all() ] [exported.helps.add(help) for help in current.helps.all()] [exported.authors.add(author) for author in current.authors.all()] exported.save() # now, re create the manifest.json versioned = exported.load_version() # this loop is there because of old .tuto import that failed with their chapter intros for container in versioned.traverse(True): if container.parent is None: continue # in old .tuto file chapter intro are represented as chapter_slug/introduction.md # instead of part_slug/chapter_slug/introduction.md corrected_intro_path = file_join( container.get_path(relative=False), "introduction.md") corrected_ccl_path = file_join(container.get_path(relative=False), "conclusion.md") if container.get_path(True) not in container.introduction: if file_exists(corrected_intro_path): container.introduction = file_join( container.get_path(relative=True), "introduction.md") else: container.introduction = None if container.get_path(True) not in container.conclusion: if file_exists(corrected_ccl_path): container.conclusion = file_join( container.get_path(relative=True), "conclusion.md") else: container.conclusion = None versioned.licence = exported.licence versioned.type = "TUTORIAL" versioned.dump_json() versioned.repository.index.add(['manifest.json' ]) # index new manifest before commit exported.sha_draft = versioned.commit_changes(u"Migration version 2") exported.old_pk = current.pk exported.save() # export beta forum post former_topic = Topic.objects.filter(key=current.pk).first() if former_topic is not None: former_topic.related_publishable_content = exported former_topic.save() former_first_post = former_topic.first_post() text = former_first_post.text text = text.replace(current.get_absolute_url_beta(), exported.get_absolute_url_beta()) former_first_post.update_content(text) former_first_post.save() exported.beta_topic = former_topic exported.save() # extract notes reacts = Note.objects.filter(tutorial__pk=current.pk)\ .select_related("author")\ .order_by("pubdate")\ .all() migrate_validation( exported, TutorialValidation.objects.filter(tutorial__pk=current.pk)) if current.last_note: export_comments(reacts, exported, TutorialRead, current.last_note.pk) if current.sha_public is not None and current.sha_public != "": published = publish_content( exported, exported.load_version(current.sha_public), False) exported.pubdate = current.pubdate exported.sha_public = current.sha_public exported.public_version = published exported.save() published.content_public_slug = exported.slug published.publication_date = current.pubdate published.save() # set mapping map_previous = PublishedContent() map_previous.content_public_slug = current.slug map_previous.content_pk = current.pk map_previous.content_type = 'TUTORIAL' map_previous.must_redirect = True # will send HTTP 301 if visited ! map_previous.content = exported map_previous.save() # fix strange notification bug authors = list(exported.authors.all()) reads_to_delete = ContentRead.objects\ .filter(content=exported)\ .exclude(user__pk__in=ContentReaction.objects .filter(related_content=exported) .exclude(author__in=authors) .values_list("author__pk", flat=True)) for read in reads_to_delete.all(): read.delete()
def migrate_articles(): articles = Article.objects.all() if len(articles) == 0: return for i in progressbar(xrange(len(articles)), "Exporting articles", 100): current = articles[i] if not os.path.exists(current.get_path(False)): sys.stderr.write( 'Invalid physical path to repository « {} », skipping\n'. format(current.get_path(False))) continue exported = PublishableContent() exported.slug = current.slug exported.type = "ARTICLE" exported.title = current.title exported.creation_date = current.create_at exported.description = current.description exported.sha_draft = current.sha_draft exported.sha_validation = current.sha_validation exported.licence = current.licence exported.js_support = current.js_support exported.pubdate = current.pubdate exported.save( ) # before updating `ManyToMany` relation, we need to save ! try: clean_commit = copy_and_clean_repo(current.get_path(False), exported.get_repo_path(False)) except InvalidGitRepositoryError as e: exported.delete() sys.stderr.write( 'Repository in « {} » is invalid, skipping\n'.format(e)) continue if clean_commit: exported.sha_draft = clean_commit # save clean up in old module to avoid any trouble current.sha_draft = clean_commit current.save() [exported.authors.add(author) for author in current.authors.all()] [ exported.subcategory.add(category) for category in current.subcategory.all() ] new_gallery = create_gallery_for_article(exported) if current.image: # migrate image using `Image()` try: path_to_image = current.image['article_illu'].url except InvalidImageFormatError: pass else: img = Image() # Create a new name for our image filename = os.path.basename(current.image['article_illu'].url) # Find original name split = filename.split('.') original_filename = split[0] + '.' + split[1] if "None" in path_to_image: # Move image in the gallery folder shutil.copyfile( os.path.join(MEDIA_ROOT, 'articles', 'None', original_filename), os.path.join(new_gallery.get_gallery_path(), original_filename)) # Update image information img.physical = os.path.join('galleries', str(new_gallery.pk), original_filename) else: # Move image in the gallery folder shutil.copyfile( os.path.join(MEDIA_ROOT, 'articles', str(current.id), original_filename), os.path.join(new_gallery.get_gallery_path(), original_filename)) # Update image information img.physical = os.path.join('galleries', str(new_gallery.pk), original_filename) img.title = 'icone de l\'article' img.slug = slugify(filename) img.pubdate = datetime.now() img.gallery = new_gallery img.save() exported.image = img # now, re create the manifest.json versioned = exported.load_version() versioned.type = "ARTICLE" if exported.licence: versioned.licence = exported.licence split_article_in_extracts(versioned) # create extracts from text exported.sha_draft = versioned.commit_changes(u'Migration version 2') exported.old_pk = current.pk exported.save() reacts = Reaction.objects.filter(article__pk=current.pk)\ .select_related("author")\ .order_by("pubdate")\ .all() if current.last_reaction: export_comments(reacts, exported, ArticleRead, current.last_reaction.pk) migrate_validation( exported, ArticleValidation.objects.filter(article__pk=current.pk)) if current.sha_public is not None and current.sha_public != "": # set mapping map_previous = PublishedContent() map_previous.content_public_slug = current.slug map_previous.content_pk = current.pk map_previous.content_type = 'ARTICLE' map_previous.must_redirect = True # will send HTTP 301 if visited ! map_previous.content = exported map_previous.save() # publish the article ! published = publish_content( exported, exported.load_version(exported.sha_draft), False) exported.pubdate = current.pubdate exported.update_date = current.update exported.sha_public = exported.sha_draft exported.public_version = published exported.save() published.content_public_slug = exported.slug published.publication_date = exported.pubdate published.save() # as we changed the structure we have to update the validation history. Yes, it's ugly. last_validation = Validation.objects.filter( content__pk=exported.pk).last() structure_validation = Validation( content=exported, version=exported.sha_public, comment_authors="Migration v2", comment_validator="yeah", status="ACCEPT", validator=last_validation.validator, date_proposition=datetime.now(), date_validation=datetime.now(), date_reserve=datetime.now()) structure_validation.save() # fix strange notification bug authors = list(exported.authors.all()) reads_to_delete = ContentRead.objects\ .filter(content=exported)\ .exclude(user__pk__in=ContentReaction.objects .filter(related_content=exported) .exclude(author__in=authors) .values_list("author__pk", flat=True)) for read in reads_to_delete.all(): read.delete()
def test_publish_content(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object ! self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual( PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue(os.path.isfile( public.get_prod_path())) # normally, an HTML file should exists self.assertIsNone( public.introduction ) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual( PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists( public.get_prod_path())) # article was removed # ... For the next tests, I will assume that the unpublication works. # 2. Mini-tutorial → Not tested, because at this point, it's the same as an article (with a different metadata) # 3. Medium-size tutorial midsize_tuto = PublishableContentFactory(type='TUTORIAL') midsize_tuto.authors.add(self.user_author) UserGalleryFactory(gallery=midsize_tuto.gallery, user=self.user_author, mode='W') midsize_tuto.licence = self.licence midsize_tuto.save() # populate with 2 chapters (1 extract each) midsize_tuto_draft = midsize_tuto.load_version() chapter1 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter1, db_object=midsize_tuto) chapter2 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter2, db_object=midsize_tuto) # publish it midsize_tuto = PublishableContent.objects.get(pk=midsize_tuto.pk) published = publish_content(midsize_tuto, midsize_tuto_draft) self.assertEqual(published.content, midsize_tuto) self.assertEqual(published.content_pk, midsize_tuto.pk) self.assertEqual(published.content_type, midsize_tuto.type) self.assertEqual(published.content_public_slug, midsize_tuto_draft.slug) self.assertEqual(published.sha_public, midsize_tuto.sha_draft) public = midsize_tuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for child in public.children: self.assertTrue(os.path.isfile( child.get_prod_path())) # an HTML file for each chapter self.assertIsNone(child.introduction) self.assertIsNone(child.conclusion) # 4. Big tutorial: bigtuto = PublishableContentFactory(type='TUTORIAL') bigtuto.authors.add(self.user_author) UserGalleryFactory(gallery=bigtuto.gallery, user=self.user_author, mode='W') bigtuto.licence = self.licence bigtuto.save() # populate with 2 part (1 chapter with 1 extract each) bigtuto_draft = bigtuto.load_version() part1 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter1 = ContainerFactory(parent=part1, db_objet=bigtuto) ExtractFactory(container=chapter1, db_object=bigtuto) part2 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter2 = ContainerFactory(parent=part2, db_objet=bigtuto) ExtractFactory(container=chapter2, db_object=bigtuto) # publish it bigtuto = PublishableContent.objects.get(pk=bigtuto.pk) published = publish_content(bigtuto, bigtuto_draft) self.assertEqual(published.content, bigtuto) self.assertEqual(published.content_pk, bigtuto.pk) self.assertEqual(published.content_type, bigtuto.type) self.assertEqual(published.content_public_slug, bigtuto_draft.slug) self.assertEqual(published.sha_public, bigtuto.sha_draft) public = bigtuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for part in public.children: self.assertTrue(os.path.isdir( part.get_prod_path())) # a directory for each part # ... and an HTML file for introduction and conclusion self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.introduction))) self.assertTrue( os.path.isfile( os.path.join(public.get_prod_path(), part.conclusion))) self.assertEqual(len(part.children), 1) for chapter in part.children: # the HTML file is located in the good directory: self.assertEqual(part.get_prod_path(), os.path.dirname(chapter.get_prod_path())) self.assertTrue(os.path.isfile( chapter.get_prod_path())) # an HTML file for each chapter self.assertIsNone(chapter.introduction) self.assertIsNone(chapter.conclusion)
def form_valid(self, form): user = self.request.user validation = Validation.objects.filter(pk=self.kwargs['pk']).last() if not validation: raise PermissionDenied if validation.validator != user: raise PermissionDenied if validation.status != 'PENDING_V': raise PermissionDenied # get database representation and validated version db_object = validation.content versioned = db_object.load_version(sha=validation.version) self.success_url = versioned.get_absolute_url( version=validation.version) try: published = publish_content( db_object, versioned, is_major_update=form.cleaned_data['is_major']) except FailureDuringPublication as e: messages.error(self.request, e.message) else: # save in database is_update = db_object.sha_public and db_object.sha_public != '' db_object.sha_public = validation.version db_object.source = form.cleaned_data['source'] db_object.sha_validation = None db_object.public_version = published if form.cleaned_data[ 'is_major'] or not is_update or db_object.pubdate is None: db_object.pubdate = datetime.now() db_object.save() # save validation object validation.comment_validator = form.cleaned_data['text'] validation.status = "ACCEPT" validation.date_validation = datetime.now() validation.save() for user in db_object.authors.all(): read = ContentRead.objects.filter(content__pk=db_object.pk, user__pk=user.pk).first() if read is None: read = ContentRead() read.user = user read.content = db_object read.save() if is_update: msg = render_to_string( 'tutorialv2/messages/validation_accept_update.md', { 'content': versioned, 'url': published.get_absolute_url_online(), 'validator': validation.validator }) else: msg = render_to_string( 'tutorialv2/messages/validation_accept_content.md', { 'content': versioned, 'url': published.get_absolute_url_online(), 'validator': validation.validator }) bot = get_object_or_404( User, username=settings.ZDS_APP['member']['bot_account']) send_mp(bot, db_object.authors.all(), _(u"Publication acceptée"), versioned.title, msg, True, direct=False) messages.success(self.request, _(u'Le contenu a bien été validé.')) self.success_url = published.get_absolute_url_online() return super(AcceptValidation, self).form_valid(form)
def load_contents(cli, _type, size, fake): """Create v2 contents""" nb_contents = size * 10 percent_contents_in_validation = 0.4 percent_contents_with_validator = 0.2 percent_contents_public = 0.3 percent_mini = 0.5 percent_medium = 0.3 percent_big = 0.2 nb_avg_containers_in_content = size nb_avg_extracts_in_content = size is_articles = _type == "ARTICLE" is_tutorials = not is_articles textual_type = u"article" if is_tutorials: textual_type = u"tutoriel" # small introduction cli.stdout.write(u'À créer: {:d} {}s'.format(nb_contents, textual_type), ending='') if is_tutorials: cli.stdout.write(u' ({: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(u' - {:g} en brouillon'.format( nb_contents * (1 - percent_contents_public - percent_contents_in_validation - percent_contents_with_validator))) cli.stdout.write(u' - {:g} en validation (dont {:g} réservés)'.format( nb_contents * (percent_contents_in_validation + percent_contents_with_validator), nb_contents * percent_contents_with_validator)) cli.stdout.write(u' - {:g} publiés'.format(nb_contents * percent_contents_public)) tps1 = time.time() # create tables with 0=draft, 1=in validation, 2=reserved, 3=published what_to_do = [] for i in range(nb_contents): what = 0 # in draft if i < percent_contents_public * nb_contents: what = 3 elif i < (percent_contents_public + percent_contents_with_validator) * nb_contents: what = 2 elif i >= (1 - percent_contents_in_validation) * nb_contents: what = 1 what_to_do.append(what) # create a table with 0=mini, 1=medium, 2=big content_sizes = [] for i in range(nb_contents): sz = 0 if i < percent_big * nb_contents: sz = 2 elif i >= (1 - percent_medium) * nb_contents: sz = 1 content_sizes.append(sz) # shuffle the whole thing random.shuffle(what_to_do) random.shuffle(content_sizes) # checks that everything is ok users = list(Profile.objects.all()) nb_users = len(users) sub_categories = list(SubCategory.objects.all()) nb_sub_categories = len(sub_categories) if nb_users == 0: cli.stdout.write( u"Il n'y a aucun membre actuellement. " u"Vous devez rajouter les membre dans vos fixtures (member)") return if nb_sub_categories == 0: cli.stdout.write( u"Il n'y a aucune catégories actuellement." u"Vous devez rajouter les catégories dans vos fixtures (category_content)" ) return perms = list( Permission.objects.filter(codename__startswith='change_').all()) staffs = list(User.objects.filter(groups__permissions__in=perms).all()) nb_staffs = len(staffs) if nb_staffs == 0: cli.stdout.write( u"Il n'y a aucun staff actuellement." u"Vous devez rajouter les staffs dans vos fixtures (staff)") return licenses = list(Licence.objects.all()) nb_licenses = len(licenses) if nb_licenses == 0: cli.stdout.write( u"Il n'y a aucune licence actuellement." u"Vous devez rajouter les licences dans vos fixtures (category_content)" ) return # create and so all: for i in range(nb_contents): sys.stdout.write("Création {} : {}/{} \r".format( textual_type, i + 1, nb_contents)) current_size = content_sizes[i] to_do = what_to_do[i] # creation: content = PublishableContentFactory(type=_type, title=fake.text(max_nb_chars=60), description=fake.sentence( nb_words=15, variable_nb_words=True)) versioned = content.load_version() if current_size == 0 or is_articles: for j in range(random.randint(1, nb_avg_extracts_in_content * 2)): ExtractFactory(container=versioned, title=fake.text(max_nb_chars=60), light=False) else: for j in range(random.randint(1, nb_avg_containers_in_content * 2)): container = ContainerFactory(parent=versioned, title=fake.text(max_nb_chars=60)) 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) 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 l in range( random.randint(1, nb_avg_extracts_in_content * 2)): ExtractFactory(container=subcontainer, title=fake.text(max_nb_chars=60), light=False) # add some informations: author = users[random.randint(0, nb_users - 1)].user content.authors.add(author) UserGalleryFactory(gallery=content.gallery, mode="W", user=author) content.licence = licenses[random.randint(0, nb_licenses - 1)] content.sha_draft = versioned.sha_draft content.subcategory.add(sub_categories[random.randint( 0, nb_sub_categories - 1)]) content.save() # then, validation if needed: if to_do > 0: valid = CValidation(content=content, version=content.sha_draft, date_proposition=datetime.now(), status="PENDING") valid.comment_validator = fake.text(max_nb_chars=200) content.sha_validation = content.sha_draft if to_do > 1: # reserve validation valid.date_reserve = datetime.now() valid.validator = staffs[random.randint(0, nb_staffs - 1)] valid.status = "PENDING_V" if to_do > 2: # publish content valid.comment_validator = fake.text(max_nb_chars=80) valid.status = "ACCEPT" valid.date_validation = datetime.now() content.sha_public = content.sha_draft published = publish_content(content, versioned) content.public_version = published valid.save() content.save() sys.stdout.flush() tps2 = time.time() cli.stdout.write(u"\nFait en {:.3f} sec".format(tps2 - tps1))