Package: kitconcept.contentcreator
kitconcept.contentcreatorThis package is the responsible for automated content creation via plone.restapi serializers/creators.Initially based oncollective.contentcreatorwritten by Johannes Raggam (@thet) and evolved and improved from it.UsageBasicIt allows to have a structure in your policy package like:|-content_creator
    |- content.json
    |- siteroot.json
    |- de.mysection.json
    |- ...
    |- images
|-content_imagesusing these names (for both files and folders) as sensible defaults. This is the
recommended way, although you can specify runners for custom JSON files (see below).and creates the content in a tree like fromcontent.jsonusing the runner, and
object by object using the standalone json files.The {file}imagesfolder is blacklisted to support the images folder to be inside the creator folder.In your setuphandlers.py you need to:fromkitconcept.contentcreator.creatorimportcontent_creator_from_foldercontent_creator_from_folder()the methodcontent_creator_from_folderhas the following signature:defcontent_creator_from_folder(folder_name=os.path.join(os.path.dirname(__file__),"content_creator"),base_image_path=os.path.join(os.path.dirname(__file__),"content_images"),default_lang=None,default_wf_state=None,ignore_wf_types=["Image","File"],logger=logger,temp_enable_content_types=[],custom_order=[],do_not_edit_if_modified_after=None,exclude=[],):The creator will bail out (raise) if any object errors on creation (or edition). There are
a couple of environment variables to control this behavior:CREATOR_DEBUGandCREATOR_CONTINUE_ON_ERROR.One can exclude elements (ids, without .json sufix) using theexcludekwargs.You can control if the edit should happen or not for a given element providing the modified date
of the element is after the one specified indo_not_edit_if_modified_afterkwargs.Creator runner given a single fileGiven a JSON file containing an array of objects to be created, this runner takes this
array content (should have plone.restapi syntax compliant structure) and creates content
out of it. You can load it using the method:load_json:fromkitconcept.contentcreator.creatorimportload_jsoncontent_structure=load_json('testcontent/content.json',__file__)Then you can call the runner with the methodcreate_item_runner:fromkitconcept.contentcreator.creatorimportcreate_item_runnercreate_item_runner(api.portal.get(),content_structure,default_lang='en',default_wf_state='published')Creator runner given a folder with multiple filesEach file should contain a single p.restapi JSON compliant object (non arrayed, can't
contain other objects). It takes the placement in the tree hierarchy and the object id
from the filename name (eg. de.beispiele.bildergroessen.json)Setup runners from external modules/packagesAlternativelly, you can create custom content creators in other packages and
call them all at the same time, via a custom adapter:fromkitconcept.contentcreator.interfacesimportICreateTestContentforname,provideringetAdapters((api.portal.get(),),ICreateTestContent):provider()this should be the declaration in the other package:@implementer(ICreateTestContent)@adapter(IPloneSiteRoot)classCreatePFGContent(object):"""Adapter to create PFG initial content."""def__init__(self,context):self.context=contextdef__call__(self):content_structure=load_json('testcontent/content.json',__file__)create_item_runner(api.portal.get(),content_structure,default_lang='en',default_wf_state='published',ignore_wf_types=['FormBooleanField','FormDateField','FormFileField','FormFixedPointField','FormIntegerField','FormLabelField','FormLinesField','FormPasswordField',],)other common use is calling from a folder:fromkitconcept.contentcreator.creatorimportcontent_creator_from_foldercontent_creator_from_folder(folder_name=os.path.join(os.path.dirname(__file__),"content_creator"),base_image_path=os.path.join(os.path.dirname(__file__),"images"),default_lang='en',default_wf_state='published',ignore_wf_types=['FormBooleanField','FormDateField','FormFileField','FormFixedPointField','FormIntegerField','FormLabelField','FormLinesField','FormPasswordField',],logger=logger,temp_enable_content_types=[],custom_order=['object-id-2.json','object-id-3.json','object-id-1.json',],)Images and FilesFor the creation of images, you can use the plone.restapi approach using the
following serialization mapping containg the file data and some additional
metadata:data- the base64 encoded contents of the fileencoding- the encoding you used to encode the data, so usuallybase64content-type- the MIME type of the filefilename- the name of the file, including extension{"...":"","@type":"File","title":"My file","file":{"data":"TG9yZW0gSXBzdW0uCg==","encoding":"base64","filename":"lorem.txt","content-type":"text/plain"}}Alternatively, you can provide the image an extra propertyset_dummy_imagewith an array of (image) field names that will create a dummy image placeholder
in the specified fields in the to be created content type:{"id":"an-image","@type":"Image","title":"Test Image","set_dummy_image":["image"]}A deprecated syntax form is also supported (it will create the image in theimagefield)::{"id":"an-image","@type":"Image","title":"Test Image","set_dummy_image":true}You can specify a real image too, using a dict in theset_local_imageJSON
attribute with the field name and the filename of the real image:{"id":"another-image","@type":"Image","title":"Another Test Image","set_local_image":{"image":"image.png"}}Again, a deprecated form is also supported (it will create the image in theimagefield):{"id":"another-image","@type":"Image","title":"Another Test Image","set_local_image":"image.png"}By default, image scales are generated immediately. To disable this,
set theCREATOR_SKIP_SCALESenvironment variable.The same syntax is valid for files:{"id":"an-file","@type":"File","title":"Test File","set_dummy_file":["file"]}The deprecated form is also supported (it will create the file in thefilefield):{"id":"an-file","@type":"File","title":"Test File","set_dummy_file":true}You can specify a real file too, using a dict in theset_local_fileJSON
attribute with the field name and the filename of the real file:{"id":"another-file","@type":"File","title":"Another Test File","set_local_file":{"file":"file.png"}}the deprecated form is also supported (it will create the file in thefilefield):{"id":"another-file","@type":"File","title":"Another Test File","set_local_file":"file.png"}For all local images and files specified, you can specify thebase_pathfor the image in thecreate_item_runner:create_item_runner(api.portal.get(),content_structure,default_lang='en',default_wf_state='published',base_image_path=__file__)TranslationsIf you are using plone.app.multilingual and creating items from a folder,
you can link translations usingtranslations.csvin this format::canonical,translation
/de/path/to/canonical,/en/path/to/translationDevelopmentRequirements:Python 3venvSetup:makeRun Static Code Analysis:makelintRun Unit / Integration Tests:maketestContributorskitconcept GmbH,info@kitconcept.comChangelog5.1.0 (2022-09-05)Change README, CHANGES, CONTRIBUTOR to markdown. @ericofUse plone/code-analysis-action@v1 for Code Analysis @ericofDirectly change blocks and blocks_layout in the root for Plone6 and above @steffenriImprove check for plone version @steffenri5.0.5 (2022-07-28)content_creator_from_foldernow accepts an optional listtypes_orderto prefer loading particular content types earlier @davisagliImproved logging to include the content type. @davisagliRefactored to usepathlibinternally. @davisagli5.0.4 (2022-07-26)Add a feature for linking translations usingtranslations.csv@davisagliAdd the option to disable creating image scales immediately
by setting theCREATOR_SKIP_SCALESenvironment variable. @davisagliIf theidin JSON doesn't match the id from the filename,
prefer the one in the JSON. @davisagli5.0.3 (2022-06-23)Don't swallow ValueError while importing a content item. @davisagli5.0.2 (2022-04-21)Fix language when the deserialization dict does not contain alanguagekey.
This was hidden by the generalreindexObjectthat was removed previously. @sneridagh5.0.1 (2022-04-20)Remove "always reindex" on finish object, since that was happening twice (on creation and on edit) @sneridaghFix on edit content issue notify event (the content was not being reindexed on deserialization) @sneridagh5.0.0 (2022-04-13)Include kitconcept.api as dependency @ericofDrop support for Python 3.7 @ericofRemove buildout @ericofUpdate Github Actions @ericof4.0.0 (2022-01-21)Breaking:Remove support for Archetypes and Python 2. @sneridaghRefactor the creator to break by default. Added a scapehatch to not to break and for
open a debug session on fail viaCREATOR_DEBUGandCREATOR_CONTINUE_ON_ERRORenvironment variables. @sneridagh3.3.0 (2022-01-11)FEATURE:Add ability to exclude files from the file list (content_creator_from_folder) @sneridaghINTERNAL:Move to latest 5.2.6 build @sneridagh3.2.0 (2021-12-03)Guess content id if missing, taking into account that the content might already be there. @sneridagh3.1.0 (2021-12-03)Use an improved logging infrasttructure @sneridagh3.0.2 (2021-11-28)Use debug log level when generating image scales @timoMake log messages more consistent @timoDo not use colors for info messages @timo3.0.1 (2021-11-11)Add classifiers to setup.py for Python 3.8, 3.9 and maturity. @timoSet effective date if the contentreview_stateispublished@sneridagh3.0.0 (2021-11-10)Explicitly include dependencies (supporting pip installations) @ericofUse plone/setup-plone@v1.0.0 in Github actions @ericofRequire plone.restapi 7.5.0 or superior (volto-slate blocks: resolveuid for links, transformer support) @ericof2.1.0 (2021-10-13)Newdo_not_edit_if_modified_afteroption. Allows to not edit if the given date is lesser than the object modification date. @sneridagh2.0.0 (2021-07-09)Breaking:Use Slate as default text block @sneridagh1.2.1 (2021-07-09)Bugfix:Add refresh of the created content for updating the serialized blocks with the
resolveuid information @sneridaghInternal:Remove some unused imports [timo]Add flake8 check on CI [timo]1.2.0 (2021-04-08)Black listimagesfoder inside the create content folders @sneridaghImprove error detection and report @sneridagh1.1.0 (2021-01-26)Improve content language detection if the field is not present @sneridaghFix and improve language inferring in the editing of an existing content @sneridagh1.0.6 (2020-05-08)Publish package on pypi. @timoAdded the from a folder content creation. @sneridagh1.0.5 (2019-11-22)Improve error reporting in create_item_runner. @timo1.0.4 (2019-11-21)Re-release. @timo1.0.3 (2019-05-06)Re-release. @sneridagh1.0.2 (2019-05-06)Nothing changed yet.1.0.1 (unreleased)Port to Python 3. @sneridaghDocumentation. @sneridagh1.0.0 (2019-03-26)Initial release. @kitconcept