Code Monkey home page Code Monkey logo

collective.jsonify's Introduction

collective.jsonify exports your Plone content to JSON.

Many packages that export data from Plone have complicated dependencies, and so only work with Plone 3.0 or higher (or not even with 3.0). collective.jsonify's only dependency is simplejson. It can be installed in any Plone version as far back as:

  • Plone 2.1 (or probably even Plone 2.0, but not tested)
  • Zope 2.6.4 (with CMF rather than Plone)
  • Python 2.2

You can use the provided export script by adding it to an external method as described below.

The exported json is a collective.transmogrifier friendly format. Install collective.jsonify on a site you want to export from, and setup an import transmogrifier pipeline on the site you're importing to, using the blueprints in the collective.jsonmigrator package.

Alternatively you can use collective.exportimport to import that data as described in https://github.com/collective/collective.exportimport#migrate-very-old-plone-versions-with-data-created-by-collective-jsonify

How to install it

Install collective.jsonify for your Plone site, so that it is available in your Plone site's PYTHONPATH, including the simplejson package. The easiest way is to use buildout, as for any other modern Plone project. Other options include:

  1. Play with PYTHONPATH manually.
  2. Use easy_install collective.jsonify or pip install collective.jsonify which will also pull simplejson.

Note: if you are working with python 2.2, then you will need to install a `tweaked branch of simplejson <https://github.com/simplejson/simplejson/tree/python2.2>`_.

Then run your Zope instance, go to the Zope root and create the necessary External Methods.

External method for exporting JSON files to the filesystem:

  • export_content:
    • id: export_content
    • module name: collective.jsonify.json_methods
    • function name: export_content

External methods for remote access from the importing Plone instance, using collective.jsonmigrator:

  • get_item
    • id: get_item
    • module name: collective.jsonify.json_methods
    • function name: get_item
  • get_children:
    • id: get_children
    • module name: collective.jsonify.json_methods
    • function name: get_children
  • get_catalog_results:
    • id: get_catalog_results
    • module name: collective.jsonify.json_methods
    • function name: get_catalog_results

It's true that External Methods are not the nicest to work with and using them makes the setup a little long. But the nice thing about External Methods is that they work in Plone 1.0 as well as in Plone 4.0, so you could potentially use collective.jsonify to migrate from very old Plone versions.

How to use it

collective.jsonify is intended to be used in conjunction with collective.jsonmigrator. There you can find an example transmogrifier pipeline that connects to the Plone site running collective.jsonify, crawls it, extracts the content and imports it into the target site.

To see what collective.jsonmigrator is actually seeing you can issue "json views" on content you want to explore:

http://localhost:8080/Plone/front-page/get_item
http://localhost:8080/Plone/front-page/get_children

The first gets all content out of front-page; the second lists all content contained inside this object and returns their ids.

Finally, you can use get_catalog_results to catalog query results as a list of paths. To use it, you need to hand your query as a base64'ed Python dict string. Here's an example of doing this with curl:

curl --data catalog_query=$(echo '{"Type": "Slide"}' | base64 -w0) \
  'http://localhost:8080/Plone/portal_catalog/get_catalog_results

Using the exporter

To export your site to a directory of JSON files use the collective.jsonify.export.export_content function.

This is how to use it with an external method:

  • Install collective.jsonify for your instance.
  • Create a script in your Zope instance Extensions directory, e.g. in BUILDOUT_ROOT/parts/instance/Extensions. Create the Extensions directory, if it doesn't exist. Create a file json_methods.py with the following contents - adapt for your needs:

    from collective.jsonify.export import export_content as export_content_orig
    
    
    def export_content(self):
        return export_content_orig(
            self,
            basedir='/tmp',  # export directory
            extra_skip_classname=['ATTopic'],
            # batch_start=5000,
            # batch_size=5000,
            # batch_previous_path='/Plone/last/exported/path'  # optional, but saves more memory because no item has to be jsonified before continuing...
        )
  • Create the "External Method" in the ZMI at the Zope root or Plone root. id: "export_content" module name: "json_methods" function name: "export_content"

    For more info on "External Methods" see: https://zope.readthedocs.io/en/latest/zopebook/ScriptingZope.html#using-external-methods

  • To start the export, open the url in your browser::

    http://localhost:8080/Plone/export_content

How to extend it

We try to cover the basic Plone types to export useful content out of Plone. We cannot predict all usecases, but if you have custom requirements it's easy to extend functionality.

To control what to export before serialzing is the fastest way to extend.. You can override the export_content "External Methods" as described above.

Example:

from collective.jsonify.export import export_content as export_content_orig

EXPORTED_TYPES = [
    "Folder",
    "Document",
    "News Item",
    "Event",
    "Link",
    "Topic",
    "File",
    "Image",
    "RichTopic",
]

EXTRA_SKIP_PATHS = [
    "/Plone/archiv/",
    "/Plone/do-not-import/",
]

# Path from which to continue the export.
# The export walks the whole site respecting the order.
# It will ignore everything untill this path is reached.
PREVIOUS = ""

def export_content(self):
    return export_content_orig(
        self,
        basedir="/var/lib/zope/json",
        skip_callback=skip_item,
        extra_skip_classname=[],
        extra_skip_id=[],
        extra_skip_paths=EXTRA_SKIP_PATHS,
        batch_start=0,
        batch_size=10000,
        batch_previous_path=PREVIOUS or None,
    )

def skip_item(item):
    """Return True if the item should be skipped"""
    portal_type = getattr(item, "portal_type", None)
    if portal_type not in EXPORTED_TYPES:
        return True

You can modify or extend the exported data by passing additional wrappers to get_item or export_content. These should to be "External Methods":

http://localhost:8080/Plone/front-page/get_item?additional_wrappers=extend_item

These hooks take the object and the serialized data as arguments.

Example:

def extend_item(obj, item):
    """Extend to work better well with collective.exportimport"""
    from Acquisition import aq_parent

    # Info about parent
    parent = aq_parent(obj)
    item["parent"] = {
        "@id": parent.absolute_url(),
        "@type": getattr(parent, "portal_type", None),
    }
    if getattr(parent.aq_base, "UID", None) is not None:
        item["parent"]["UID"] = parent.UID()

    # Review state
    try:
        review_state = obj.portal_workflow.getInfoFor(obj, "review_state")
    except Exception, e:
        review_state = None
    item["review_state"] = review_state

    # Block inheritance of local roles
    item["_ac_local_roles_block"] = getattr(obj.aq_base, "__ac_local_roles_block__", False)

    return item

collective.jsonify's People

Contributors

agitator avatar ale-rt avatar buchi avatar danjacka avatar djowett avatar garbas avatar gborelli avatar gforcada avatar gogobd avatar gotcha avatar hvelarde avatar instification avatar jean avatar jensens avatar jone avatar jsbueno avatar lentinj avatar maartenkling avatar mauritsvanrees avatar openprojects avatar pbauer avatar realefab avatar rristow avatar sunew avatar svx avatar thet avatar tomgross avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

collective.jsonify's Issues

export_content raises AttributeError: get with Plone 2.8.7

Same issue as #48

Commit 192fed7 in collective.jsonify 1.5 causes an exception in export_content with Zope 2.8.7-final, python 2.3.5, linux3:

Traceback (most recent call last):
File "/home/software/zope/2.8/lib/python/ZPublisher/Publish.py", line 114, in publish
request, bind=1)
File "/home/software/zope/2.8/lib/python/ZPublisher/mapply.py", line 88, in mapply
if debug is not None: return debug(object,args,context)
File "/home/software/zope/2.8/lib/python/ZPublisher/Publish.py", line 40, in call_object
result=apply(object,args) # Type s to step into published object.
File "/home/software/zope/2.8/lib/python/Products/ExternalMethod/ExternalMethod.py", line 225, in call
try: return f(*args, **kw)
File "/home/zope/productie/Extensions/json_methods.py", line 16, in export_content
extra_skip_classname=[], # optional list of classnames to skip
File "/home/software/python/2.3.5/lib/python2.3/site-packages/collective.jsonify-1.5-py2.3.egg/collective/jsonify/export.py", line 266, in export_content
write(walk(self, skip_callback=skip_callback))
File "/home/software/python/2.3.5/lib/python2.3/site-packages/collective.jsonify-1.5-py2.3.egg/collective/jsonify/export.py", line 337, in write
for item in items:
File "/home/software/python/2.3.5/lib/python2.3/site-packages/collective.jsonify-1.5-py2.3.egg/collective/jsonify/export.py", line 299, in walk
item = folder.get(item_id)
AttributeError: get

error

Please fix:

--- a/collective/jsonify/wrapper.py
+++ b/collective/jsonify/wrapper.py
@@ -125,7 +125,7 @@ class Wrapper(dict):
         """ Local roles of object
             :keys: _local_roles
         """
-        self['_local_roles'] = {}
+        self['_ac_local_roles'] = {}
         if getattr(self.context, '__ac_local_roles__', False):
             for key, val in self.context.__ac_local_roles__.items():
                 if key is not None:
                    self['_ac_local_roles'][key] = val

Custom Dexterity types missing UID in export

After running an export from a Plone 4 site, I realized the custom types do not have a UID in the json files. The other types do have the UID. This causes resolveuid links to break.

New release

Can we have a new release of this package, please?

base64 Out of memoy

We were running into memory issues when we were migrating high resolution images. Quick research showed that there's an alternative implementation for base64 that's better. I'm currently field-testing this in a fork, will come back later to submit a pull request.

Export review_state

While the latest review state is exported as part of the _workflow_history, it would be nice to have this exported as its own key/value pair.

License clarification

There is no LICENSE or COPYING file for this project. I see the setup.py file indicates the license is GPL.

I would suggest licensing this project under the AGPL3 or GPL3 license. Directions on how to apply the license are at the bottom of the license file under the How to Apply These Terms to Your New Programs heading. If you would like me to submit a PR to make this easier, I would be happy to do that.

new release

@tomgross can you grant me (pypi: thet) and @djowett (pypi?) release rights on pypi? we want to make a new release of collective.jsonify.

jsonify.get_item() fails due to AttributeError exception with isDiscussionAllowedFor

Hi,

I'm using Plone 4.2.5. When I attempt to use get_item() against anything in my site, I see the following:

from collective.jsonify import get_item
site=app['SITENAME']
print get_item(site['foo'])

results in the following:

ERROR: exception wrapping object: isDiscussionAllowedFor
['  File "/home/mcv21/falconsvn/light/src/collective.jsonify/collective/jsonify/methods.py", line 29, in get_item\n    context_dict = Wrapper(self)\n',
 '  File "/home/mcv21/falconsvn/light/src/collective.jsonify/collective/jsonify/wrapper.py", line 25, in __init__\n    getattr(self, method)()\n',
 '  File "/home/mcv21/falconsvn/light/src/collective.jsonify/collective/jsonify/wrapper.py", line 365, in get_archetypes_fields\n    value = self._get_at_field_value(field)\n',
 '  File "/home/mcv21/falconsvn/light/src/collective.jsonify/collective/jsonify/wrapper.py", line 334, in _get_at_field_value\n    return getattr(self.context, field.accessor)()\n',
 '  File "/home/mcv21/zope/eggs/Products.Archetypes-1.8.6-py2.7.egg/Products/Archetypes/ExtensibleMetadata.py", line 245, in isDiscussable\n    return dtool.isDiscussionAllowedFor(self)\n']

After some discussion on plone-users, Daniel Jowett suggested I try his fork of this code, https://github.com/djowett/collective.jsonify/ which has a few differences in how it handles archetypes fields. That works fine, though I'm not sure exactly what the necessary change is, and I'm guessing you can run git diff as well as I can ;-)

Thanks,

Matthew

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.