.. _subclassing_import-export: Pulp Import/Export ================== The Pulp Import/Export process is based around the `Django Import/Export library `_ . To be 'exportable/importable', your plugin must define a ``modelresource`` module at ``/app/modelresource.py``. The module must contain a ModelResource subclass for each Model you want to expose, and it must define an ``IMPORT_ORDER`` ordered list for all such ModelResources. QueryModelResource ~~~~~~~~~~~~~~~~~~ If you don't need to do anything "special" to export your Model you can subclass ``pulpcore.plugin.importexport.QueryModelResource``. This only requires you to provide the ``Meta.model`` class for the Model being export/imported, and to override the ``set_up_queryset(self)`` method to define a limiting filter. QueryModelResource is instantiated by the export process with the RepositoryVersion being exported (``self.repo_version``). An example ``QueryModelResource`` subclasses, for import/exporting the ``Bar`` Model from ``pulp_foo``, would look like this:: class BarResource(QueryModelResource): """ Resource for import/export of foo_bar entities """ def set_up_queryset(self): """ :return: Bars specific to a specified repo-version. """ return Bar.objects.filter(pk__in=self.repo_version.content) class Meta: model = Bar BaseContentResource ~~~~~~~~~~~~~~~~~~~~ The ``BaseContentResource`` class provides a base class for exporting ``Content``. ``BaseContentResource`` provides extra functionality on top of ``QueryModelResource`` specific to handling the exporting and importing of Content such as handling of Content-specific fields like ``upstream_id``. An example of subclassing ``BaseContentResource`` looks like:: class MyContentResource(BaseContentResource): """ Resource for import/export of MyContent. """ def set_up_queryset(self): """ :return: MyContent specific to a specified repo-version. """ return MyContent.objects.filter(pk__in=self.repo_version.content) class Meta: model = MyContent modelresource.py ~~~~~~~~~~~~~~~~ A simple ``modelresource.py`` module is the one for the ``pulp_file`` plugin. It looks like this:: from pulpcore.plugin.importexport import BaseContentResource from pulp_file.app.models import FileContent class FileContentResource(BaseContentResource): """ Resource for import/export of file_filecontent entities """ def set_up_queryset(self): """ :return: FileContents specific to a specified repo-version. """ return FileContent.objects.filter(pk__in=self.repo_version.content) class Meta: model = FileContent IMPORT_ORDER = [FileContentResource] content_mapping ~~~~~~~~~~~~~~~ By default, all the Content that gets imported is automatically associated with the Repository it is stored with inside the export archive. In some cases, this may not be desirable. One such case is when there is Content that is tied to a sub_repo but not directly to the Repository itself. Another case is where you may have Content you want imported but not associated with a Repositoy. In such cases, you can set a ``content_mapping`` property on the Resource. The ``content_mapping`` property should be a dictionary that maps repository names to a list of content_ids. The importer code in pulp will combine the ``content_mappings`` across Resources and export them to a ``content_mapping.json`` file that it will use during import to map Content to Repositories. Here is an example that deals with subrepos:: class MyContentResource(BaseContentResource): """ Resource for import/export of MyContent. """ def __init__(self, *args, **kwargs): """Override __init__ to set content_mapping to a dict.""" self.content_mapping = {} super().__init__(*args, **kwargs) def set_up_queryset(self): """Set up the queryset and our content_mapping.""" content = MyContent.objects.filter(pk__in=self.repo_version.content) self.content_mapping[self.repository_version.repository.name] = content for repo in self.subrepos(self.repo_version): subrepo_content = repo.latest_repository_version.content self.content_mapping[repo.name] = subrepo_content content |= subrepo_content return content class Meta: model = MyContent