We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
PuilpImport fails post-Domains (whether domains are enabled or not)
**Version**
core/3.23

**Describe the bug**
Domains adds a field to content "pulp_domain", which contains the pulp_id of the associated domain (or of the default-domain). Export exports that field, so import tries to hook it back up on the downstream side. The downstream "default" domain has a different pulp_domain, so the import fails with a traceback like this:
```
pulp [b2a311abd716444aada1d7ff310a5eb1]: pulpcore.tasking.pulpcore_worker:INFO:   File "/src/pulpcore/pulpcore/tasking/pulpcore_worker.py", line 458, in _perform_task
    result = func(*args, **kwargs)
  File "/src/pulpcore/pulpcore/app/tasks/importer.py", line 482, in pulp_import
    for ar_result in _import_file(os.path.join(temp_dir, ARTIFACT_FILE), ArtifactResource):
  File "/src/pulpcore/pulpcore/app/tasks/importer.py", line 143, in _import_file
    a_result = resource.import_data(data, raise_errors=True)
  File "/usr/local/lib/python3.8/site-packages/import_export/resources.py", line 813, in import_data
    result = self.import_data_inner(
  File "/usr/local/lib/python3.8/site-packages/import_export/resources.py", line 882, in import_data_inner
    raise row_result.errors[-1].error
  File "/usr/local/lib/python3.8/site-packages/import_export/resources.py", line 737, in import_row
    self.import_obj(instance, row, dry_run, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/import_export/resources.py", line 557, in import_obj
    self.import_field(field, obj, data, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/import_export/resources.py", line 540, in import_field
    field.save(obj, data, is_m2m, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/import_export/fields.py", line 119, in save
    cleaned = self.clean(data, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/import_export/fields.py", line 75, in clean
    value = self.widget.clean(value, row=data, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/import_export/widgets.py", line 423, in clean
    return self.get_queryset(value, row, **kwargs).get(**{self.field: val})
  File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 435, in get
    raise self.model.DoesNotExist(
```

**To Reproduce**
* Sync a repo.
* Export it.
* Reset the pulp-database (or move the export to a different instance)
* Attempt to import it.

**Expected behavior**
Import succeeds.





--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pulpcore/app/modelresource.py`
Content:
```
1 from import_export import fields
2 from import_export.widgets import ForeignKeyWidget
3 from logging import getLogger
4 
5 from pulpcore.app.models.content import (
6     Artifact,
7     Content,
8     ContentArtifact,
9 )
10 from pulpcore.app.models.repository import Repository
11 from pulpcore.constants import ALL_KNOWN_CONTENT_CHECKSUMS
12 from pulpcore.plugin.importexport import QueryModelResource
13 
14 
15 log = getLogger(__name__)
16 
17 
18 #
19 # Artifact and Repository are different from other import-export entities, in that they are not
20 # repo-version-specific.
21 #
22 class ArtifactResource(QueryModelResource):
23     """Resource for import/export of artifacts."""
24 
25     def before_import_row(self, row, **kwargs):
26         """
27         Sets digests to None if they are blank strings.
28 
29         Args:
30             row (tablib.Dataset row): incoming import-row representing a single Variant.
31             kwargs: args passed along from the import() call.
32 
33         """
34         # the export converts None to blank strings but sha384 and sha512 have unique constraints
35         # that get triggered if they are blank. convert checksums back into None if they are blank.
36         for checksum in ALL_KNOWN_CONTENT_CHECKSUMS:
37             if row[checksum] == "":
38                 row[checksum] = None
39 
40     class Meta:
41         model = Artifact
42         exclude = (
43             "pulp_id",
44             "pulp_created",
45             "pulp_last_updated",
46         )
47         import_id_fields = ("sha256",)
48 
49 
50 class RepositoryResource(QueryModelResource):
51     class Meta:
52         model = Repository
53         import_id_fields = ("name",)
54         exclude = (
55             "pulp_id",
56             "pulp_created",
57             "pulp_last_updated",
58             "content",
59             "next_version",
60             "repository_ptr",
61             "remote",
62             "pulp_labels",
63         )
64 
65 
66 class ContentArtifactResource(QueryModelResource):
67     """
68     Handles import/export of the ContentArtifact model.
69 
70     ContentArtifact is different from other import-export entities because it has no 'natural key'
71     other than a pulp_id, which aren't shared across instances. We do some magic to link up
72     ContentArtifacts to their matching (already-imported) Content.
73 
74     Some plugin-models have sub-repositories. We take advantage of the content-mapping
75     machinery to account for those contentartifacts as well.
76     """
77 
78     artifact = fields.Field(
79         column_name="artifact", attribute="artifact", widget=ForeignKeyWidget(Artifact, "sha256")
80     )
81 
82     def __init__(self, repo_version=None, content_mapping=None):
83         self.content_mapping = content_mapping
84         super().__init__(repo_version)
85 
86     def before_import_row(self, row, **kwargs):
87         """
88         Fixes the content-ptr of an incoming content-artifact row at import time.
89 
90         Finds the 'original uuid' of the Content for this row, looks it up as the
91         'upstream_id' of imported Content, and then replaces the Content-pk with its
92         (new) uuid.
93 
94         Args:
95             row (tablib.Dataset row): incoming import-row representing a single ContentArtifact.
96             kwargs: args passed along from the import() call.
97 
98         Returns:
99             (tablib.Dataset row): row that now points to the new downstream uuid for its content.
100         """
101 
102         linked_content = Content.objects.get(upstream_id=row["content"])
103         row["content"] = str(linked_content.pulp_id)
104 
105     def set_up_queryset(self):
106         vers_content = ContentArtifact.objects.filter(content__in=self.repo_version.content)
107         if self.content_mapping:
108             all_content = []
109             for content_ids in self.content_mapping.values():
110                 all_content.extend(content_ids)
111             vers_content = vers_content.union(
112                 ContentArtifact.objects.filter(content__in=all_content)
113             )
114         return vers_content.order_by("content", "relative_path")
115 
116     class Meta:
117         model = ContentArtifact
118         import_id_fields = (
119             "content",
120             "relative_path",
121         )
122         exclude = (
123             "pulp_created",
124             "pulp_last_updated",
125             "_artifacts",
126             "pulp_id",
127         )
128
```

Path: `pulpcore/plugin/importexport.py`
Content:
```
1 from import_export import resources
2 
3 
4 class QueryModelResource(resources.ModelResource):
5     """
6     A ModelResource that knows the RepositoryVersion to use to filter its query
7 
8     QueryModelResource has-a repository-version that can be used to limit its export, and a
9     queryset that is derived from that repository-version.
10 
11     A plugin-writer will subclass their ModelResources from QueryModelResource,
12     and use it to define the limiting query
13 
14     Attributes:
15 
16         repo_version (models.RepositoryVersion): The RepositoryVersion whose content we would like
17             to export
18         queryset (django.db.models.query.QuerySet): filtering queryset for this resource
19             (driven by repo_version)
20     """
21 
22     def set_up_queryset(self):
23         return None
24 
25     def __init__(self, repo_version=None):
26         self.repo_version = repo_version
27         if repo_version:
28             self.queryset = self.set_up_queryset()
29 
30     class Meta:
31         exclude = ("pulp_id", "pulp_created", "pulp_last_updated")
32 
33 
34 class BaseContentResource(QueryModelResource):
35     """
36     A QueryModelResource that knows how to fill in the 'upstream_id' export-field
37 
38     BaseContentResource knows to de/hydrate upstream_id with the content-being-exported's pulp_id.
39 
40     All Content-based resources being import/exported should subclass from this class.
41     """
42 
43     # An optional mapping that maps Content to Repositories. Useful when Content is sometimes not
44     # tied directly to a Repository but rather to a subrepo. Formatting:
45     #
46     #     {"<repo name>": ["<content upstream_id>", "..."]}
47     #
48     content_mapping = None
49 
50     class Meta:
51         exclude = QueryModelResource.Meta.exclude + ("_artifacts", "content", "content_ptr")
52 
53     def dehydrate_upstream_id(self, content):
54         return str(content.pulp_id)
55
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pulpcore/app/modelresource.py b/pulpcore/app/modelresource.py
--- a/pulpcore/app/modelresource.py
+++ b/pulpcore/app/modelresource.py
@@ -31,6 +31,8 @@
             kwargs: args passed along from the import() call.
 
         """
+        super().before_import_row(row, **kwargs)
+
         # the export converts None to blank strings but sha384 and sha512 have unique constraints
         # that get triggered if they are blank. convert checksums back into None if they are blank.
         for checksum in ALL_KNOWN_CONTENT_CHECKSUMS:
@@ -44,13 +46,19 @@
             "pulp_created",
             "pulp_last_updated",
         )
-        import_id_fields = ("sha256",)
+        import_id_fields = (
+            "pulp_domain",
+            "sha256",
+        )
 
 
 class RepositoryResource(QueryModelResource):
     class Meta:
         model = Repository
-        import_id_fields = ("name",)
+        import_id_fields = (
+            "pulp_domain",
+            "name",
+        )
         exclude = (
             "pulp_id",
             "pulp_created",
@@ -98,6 +106,7 @@
         Returns:
             (tablib.Dataset row): row that now points to the new downstream uuid for its content.
         """
+        super().before_import_row(row, **kwargs)
 
         linked_content = Content.objects.get(upstream_id=row["content"])
         row["content"] = str(linked_content.pulp_id)
diff --git a/pulpcore/plugin/importexport.py b/pulpcore/plugin/importexport.py
--- a/pulpcore/plugin/importexport.py
+++ b/pulpcore/plugin/importexport.py
@@ -1,4 +1,5 @@
 from import_export import resources
+from pulpcore.app.util import get_domain_pk
 
 
 class QueryModelResource(resources.ModelResource):
@@ -19,6 +20,21 @@
             (driven by repo_version)
     """
 
+    def before_import_row(self, row, **kwargs):
+        """
+        Sets pulp_domain/_pulp_domain to the current-domain on import.
+        Args:
+            row (tablib.Dataset row): incoming import-row representing a single Variant.
+            kwargs: args passed along from the import() call.
+        """
+        # There is probably a more pythonic/elegant way to do the following - but I am deliberately
+        # opting for "verbose but COMPLETELY CLEAR" here.
+        if "_pulp_domain" in row:
+            row["_pulp_domain"] = get_domain_pk()
+
+        if "pulp_domain" in row:
+            row["pulp_domain"] = get_domain_pk()
+
     def set_up_queryset(self):
         return None

{"golden_diff": "diff --git a/pulpcore/app/modelresource.py b/pulpcore/app/modelresource.py\n--- a/pulpcore/app/modelresource.py\n+++ b/pulpcore/app/modelresource.py\n@@ -31,6 +31,8 @@\n             kwargs: args passed along from the import() call.\n \n         \"\"\"\n+        super().before_import_row(row, **kwargs)\n+\n         # the export converts None to blank strings but sha384 and sha512 have unique constraints\n         # that get triggered if they are blank. convert checksums back into None if they are blank.\n         for checksum in ALL_KNOWN_CONTENT_CHECKSUMS:\n@@ -44,13 +46,19 @@\n             \"pulp_created\",\n             \"pulp_last_updated\",\n         )\n-        import_id_fields = (\"sha256\",)\n+        import_id_fields = (\n+            \"pulp_domain\",\n+            \"sha256\",\n+        )\n \n \n class RepositoryResource(QueryModelResource):\n     class Meta:\n         model = Repository\n-        import_id_fields = (\"name\",)\n+        import_id_fields = (\n+            \"pulp_domain\",\n+            \"name\",\n+        )\n         exclude = (\n             \"pulp_id\",\n             \"pulp_created\",\n@@ -98,6 +106,7 @@\n         Returns:\n             (tablib.Dataset row): row that now points to the new downstream uuid for its content.\n         \"\"\"\n+        super().before_import_row(row, **kwargs)\n \n         linked_content = Content.objects.get(upstream_id=row[\"content\"])\n         row[\"content\"] = str(linked_content.pulp_id)\ndiff --git a/pulpcore/plugin/importexport.py b/pulpcore/plugin/importexport.py\n--- a/pulpcore/plugin/importexport.py\n+++ b/pulpcore/plugin/importexport.py\n@@ -1,4 +1,5 @@\n from import_export import resources\n+from pulpcore.app.util import get_domain_pk\n \n \n class QueryModelResource(resources.ModelResource):\n@@ -19,6 +20,21 @@\n             (driven by repo_version)\n     \"\"\"\n \n+    def before_import_row(self, row, **kwargs):\n+        \"\"\"\n+        Sets pulp_domain/_pulp_domain to the current-domain on import.\n+        Args:\n+            row (tablib.Dataset row): incoming import-row representing a single Variant.\n+            kwargs: args passed along from the import() call.\n+        \"\"\"\n+        # There is probably a more pythonic/elegant way to do the following - but I am deliberately\n+        # opting for \"verbose but COMPLETELY CLEAR\" here.\n+        if \"_pulp_domain\" in row:\n+            row[\"_pulp_domain\"] = get_domain_pk()\n+\n+        if \"pulp_domain\" in row:\n+            row[\"pulp_domain\"] = get_domain_pk()\n+\n     def set_up_queryset(self):\n         return None\n", "issue": "PuilpImport fails post-Domains (whether domains are enabled or not)\n**Version**\r\ncore/3.23\r\n\r\n**Describe the bug**\r\nDomains adds a field to content \"pulp_domain\", which contains the pulp_id of the associated domain (or of the default-domain). Export exports that field, so import tries to hook it back up on the downstream side. The downstream \"default\" domain has a different pulp_domain, so the import fails with a traceback like this:\r\n```\r\npulp [b2a311abd716444aada1d7ff310a5eb1]: pulpcore.tasking.pulpcore_worker:INFO:   File \"/src/pulpcore/pulpcore/tasking/pulpcore_worker.py\", line 458, in _perform_task\r\n    result = func(*args, **kwargs)\r\n  File \"/src/pulpcore/pulpcore/app/tasks/importer.py\", line 482, in pulp_import\r\n    for ar_result in _import_file(os.path.join(temp_dir, ARTIFACT_FILE), ArtifactResource):\r\n  File \"/src/pulpcore/pulpcore/app/tasks/importer.py\", line 143, in _import_file\r\n    a_result = resource.import_data(data, raise_errors=True)\r\n  File \"/usr/local/lib/python3.8/site-packages/import_export/resources.py\", line 813, in import_data\r\n    result = self.import_data_inner(\r\n  File \"/usr/local/lib/python3.8/site-packages/import_export/resources.py\", line 882, in import_data_inner\r\n    raise row_result.errors[-1].error\r\n  File \"/usr/local/lib/python3.8/site-packages/import_export/resources.py\", line 737, in import_row\r\n    self.import_obj(instance, row, dry_run, **kwargs)\r\n  File \"/usr/local/lib/python3.8/site-packages/import_export/resources.py\", line 557, in import_obj\r\n    self.import_field(field, obj, data, **kwargs)\r\n  File \"/usr/local/lib/python3.8/site-packages/import_export/resources.py\", line 540, in import_field\r\n    field.save(obj, data, is_m2m, **kwargs)\r\n  File \"/usr/local/lib/python3.8/site-packages/import_export/fields.py\", line 119, in save\r\n    cleaned = self.clean(data, **kwargs)\r\n  File \"/usr/local/lib/python3.8/site-packages/import_export/fields.py\", line 75, in clean\r\n    value = self.widget.clean(value, row=data, **kwargs)\r\n  File \"/usr/local/lib/python3.8/site-packages/import_export/widgets.py\", line 423, in clean\r\n    return self.get_queryset(value, row, **kwargs).get(**{self.field: val})\r\n  File \"/usr/local/lib/python3.8/site-packages/django/db/models/query.py\", line 435, in get\r\n    raise self.model.DoesNotExist(\r\n```\r\n\r\n**To Reproduce**\r\n* Sync a repo.\r\n* Export it.\r\n* Reset the pulp-database (or move the export to a different instance)\r\n* Attempt to import it.\r\n\r\n**Expected behavior**\r\nImport succeeds.\r\n\r\n\r\n\r\n\n", "before_files": [{"content": "from import_export import fields\nfrom import_export.widgets import ForeignKeyWidget\nfrom logging import getLogger\n\nfrom pulpcore.app.models.content import (\n    Artifact,\n    Content,\n    ContentArtifact,\n)\nfrom pulpcore.app.models.repository import Repository\nfrom pulpcore.constants import ALL_KNOWN_CONTENT_CHECKSUMS\nfrom pulpcore.plugin.importexport import QueryModelResource\n\n\nlog = getLogger(__name__)\n\n\n#\n# Artifact and Repository are different from other import-export entities, in that they are not\n# repo-version-specific.\n#\nclass ArtifactResource(QueryModelResource):\n    \"\"\"Resource for import/export of artifacts.\"\"\"\n\n    def before_import_row(self, row, **kwargs):\n        \"\"\"\n        Sets digests to None if they are blank strings.\n\n        Args:\n            row (tablib.Dataset row): incoming import-row representing a single Variant.\n            kwargs: args passed along from the import() call.\n\n        \"\"\"\n        # the export converts None to blank strings but sha384 and sha512 have unique constraints\n        # that get triggered if they are blank. convert checksums back into None if they are blank.\n        for checksum in ALL_KNOWN_CONTENT_CHECKSUMS:\n            if row[checksum] == \"\":\n                row[checksum] = None\n\n    class Meta:\n        model = Artifact\n        exclude = (\n            \"pulp_id\",\n            \"pulp_created\",\n            \"pulp_last_updated\",\n        )\n        import_id_fields = (\"sha256\",)\n\n\nclass RepositoryResource(QueryModelResource):\n    class Meta:\n        model = Repository\n        import_id_fields = (\"name\",)\n        exclude = (\n            \"pulp_id\",\n            \"pulp_created\",\n            \"pulp_last_updated\",\n            \"content\",\n            \"next_version\",\n            \"repository_ptr\",\n            \"remote\",\n            \"pulp_labels\",\n        )\n\n\nclass ContentArtifactResource(QueryModelResource):\n    \"\"\"\n    Handles import/export of the ContentArtifact model.\n\n    ContentArtifact is different from other import-export entities because it has no 'natural key'\n    other than a pulp_id, which aren't shared across instances. We do some magic to link up\n    ContentArtifacts to their matching (already-imported) Content.\n\n    Some plugin-models have sub-repositories. We take advantage of the content-mapping\n    machinery to account for those contentartifacts as well.\n    \"\"\"\n\n    artifact = fields.Field(\n        column_name=\"artifact\", attribute=\"artifact\", widget=ForeignKeyWidget(Artifact, \"sha256\")\n    )\n\n    def __init__(self, repo_version=None, content_mapping=None):\n        self.content_mapping = content_mapping\n        super().__init__(repo_version)\n\n    def before_import_row(self, row, **kwargs):\n        \"\"\"\n        Fixes the content-ptr of an incoming content-artifact row at import time.\n\n        Finds the 'original uuid' of the Content for this row, looks it up as the\n        'upstream_id' of imported Content, and then replaces the Content-pk with its\n        (new) uuid.\n\n        Args:\n            row (tablib.Dataset row): incoming import-row representing a single ContentArtifact.\n            kwargs: args passed along from the import() call.\n\n        Returns:\n            (tablib.Dataset row): row that now points to the new downstream uuid for its content.\n        \"\"\"\n\n        linked_content = Content.objects.get(upstream_id=row[\"content\"])\n        row[\"content\"] = str(linked_content.pulp_id)\n\n    def set_up_queryset(self):\n        vers_content = ContentArtifact.objects.filter(content__in=self.repo_version.content)\n        if self.content_mapping:\n            all_content = []\n            for content_ids in self.content_mapping.values():\n                all_content.extend(content_ids)\n            vers_content = vers_content.union(\n                ContentArtifact.objects.filter(content__in=all_content)\n            )\n        return vers_content.order_by(\"content\", \"relative_path\")\n\n    class Meta:\n        model = ContentArtifact\n        import_id_fields = (\n            \"content\",\n            \"relative_path\",\n        )\n        exclude = (\n            \"pulp_created\",\n            \"pulp_last_updated\",\n            \"_artifacts\",\n            \"pulp_id\",\n        )\n", "path": "pulpcore/app/modelresource.py"}, {"content": "from import_export import resources\n\n\nclass QueryModelResource(resources.ModelResource):\n    \"\"\"\n    A ModelResource that knows the RepositoryVersion to use to filter its query\n\n    QueryModelResource has-a repository-version that can be used to limit its export, and a\n    queryset that is derived from that repository-version.\n\n    A plugin-writer will subclass their ModelResources from QueryModelResource,\n    and use it to define the limiting query\n\n    Attributes:\n\n        repo_version (models.RepositoryVersion): The RepositoryVersion whose content we would like\n            to export\n        queryset (django.db.models.query.QuerySet): filtering queryset for this resource\n            (driven by repo_version)\n    \"\"\"\n\n    def set_up_queryset(self):\n        return None\n\n    def __init__(self, repo_version=None):\n        self.repo_version = repo_version\n        if repo_version:\n            self.queryset = self.set_up_queryset()\n\n    class Meta:\n        exclude = (\"pulp_id\", \"pulp_created\", \"pulp_last_updated\")\n\n\nclass BaseContentResource(QueryModelResource):\n    \"\"\"\n    A QueryModelResource that knows how to fill in the 'upstream_id' export-field\n\n    BaseContentResource knows to de/hydrate upstream_id with the content-being-exported's pulp_id.\n\n    All Content-based resources being import/exported should subclass from this class.\n    \"\"\"\n\n    # An optional mapping that maps Content to Repositories. Useful when Content is sometimes not\n    # tied directly to a Repository but rather to a subrepo. Formatting:\n    #\n    #     {\"<repo name>\": [\"<content upstream_id>\", \"...\"]}\n    #\n    content_mapping = None\n\n    class Meta:\n        exclude = QueryModelResource.Meta.exclude + (\"_artifacts\", \"content\", \"content_ptr\")\n\n    def dehydrate_upstream_id(self, content):\n        return str(content.pulp_id)\n", "path": "pulpcore/plugin/importexport.py"}], "after_files": [{"content": "from import_export import fields\nfrom import_export.widgets import ForeignKeyWidget\nfrom logging import getLogger\n\nfrom pulpcore.app.models.content import (\n    Artifact,\n    Content,\n    ContentArtifact,\n)\nfrom pulpcore.app.models.repository import Repository\nfrom pulpcore.constants import ALL_KNOWN_CONTENT_CHECKSUMS\nfrom pulpcore.plugin.importexport import QueryModelResource\n\n\nlog = getLogger(__name__)\n\n\n#\n# Artifact and Repository are different from other import-export entities, in that they are not\n# repo-version-specific.\n#\nclass ArtifactResource(QueryModelResource):\n    \"\"\"Resource for import/export of artifacts.\"\"\"\n\n    def before_import_row(self, row, **kwargs):\n        \"\"\"\n        Sets digests to None if they are blank strings.\n\n        Args:\n            row (tablib.Dataset row): incoming import-row representing a single Variant.\n            kwargs: args passed along from the import() call.\n\n        \"\"\"\n        super().before_import_row(row, **kwargs)\n\n        # the export converts None to blank strings but sha384 and sha512 have unique constraints\n        # that get triggered if they are blank. convert checksums back into None if they are blank.\n        for checksum in ALL_KNOWN_CONTENT_CHECKSUMS:\n            if row[checksum] == \"\":\n                row[checksum] = None\n\n    class Meta:\n        model = Artifact\n        exclude = (\n            \"pulp_id\",\n            \"pulp_created\",\n            \"pulp_last_updated\",\n        )\n        import_id_fields = (\n            \"pulp_domain\",\n            \"sha256\",\n        )\n\n\nclass RepositoryResource(QueryModelResource):\n    class Meta:\n        model = Repository\n        import_id_fields = (\n            \"pulp_domain\",\n            \"name\",\n        )\n        exclude = (\n            \"pulp_id\",\n            \"pulp_created\",\n            \"pulp_last_updated\",\n            \"content\",\n            \"next_version\",\n            \"repository_ptr\",\n            \"remote\",\n            \"pulp_labels\",\n        )\n\n\nclass ContentArtifactResource(QueryModelResource):\n    \"\"\"\n    Handles import/export of the ContentArtifact model.\n\n    ContentArtifact is different from other import-export entities because it has no 'natural key'\n    other than a pulp_id, which aren't shared across instances. We do some magic to link up\n    ContentArtifacts to their matching (already-imported) Content.\n\n    Some plugin-models have sub-repositories. We take advantage of the content-mapping\n    machinery to account for those contentartifacts as well.\n    \"\"\"\n\n    artifact = fields.Field(\n        column_name=\"artifact\", attribute=\"artifact\", widget=ForeignKeyWidget(Artifact, \"sha256\")\n    )\n\n    def __init__(self, repo_version=None, content_mapping=None):\n        self.content_mapping = content_mapping\n        super().__init__(repo_version)\n\n    def before_import_row(self, row, **kwargs):\n        \"\"\"\n        Fixes the content-ptr of an incoming content-artifact row at import time.\n\n        Finds the 'original uuid' of the Content for this row, looks it up as the\n        'upstream_id' of imported Content, and then replaces the Content-pk with its\n        (new) uuid.\n\n        Args:\n            row (tablib.Dataset row): incoming import-row representing a single ContentArtifact.\n            kwargs: args passed along from the import() call.\n\n        Returns:\n            (tablib.Dataset row): row that now points to the new downstream uuid for its content.\n        \"\"\"\n        super().before_import_row(row, **kwargs)\n\n        linked_content = Content.objects.get(upstream_id=row[\"content\"])\n        row[\"content\"] = str(linked_content.pulp_id)\n\n    def set_up_queryset(self):\n        vers_content = ContentArtifact.objects.filter(content__in=self.repo_version.content)\n        if self.content_mapping:\n            all_content = []\n            for content_ids in self.content_mapping.values():\n                all_content.extend(content_ids)\n            vers_content = vers_content.union(\n                ContentArtifact.objects.filter(content__in=all_content)\n            )\n        return vers_content.order_by(\"content\", \"relative_path\")\n\n    class Meta:\n        model = ContentArtifact\n        import_id_fields = (\n            \"content\",\n            \"relative_path\",\n        )\n        exclude = (\n            \"pulp_created\",\n            \"pulp_last_updated\",\n            \"_artifacts\",\n            \"pulp_id\",\n        )\n", "path": "pulpcore/app/modelresource.py"}, {"content": "from import_export import resources\nfrom pulpcore.app.util import get_domain_pk\n\n\nclass QueryModelResource(resources.ModelResource):\n    \"\"\"\n    A ModelResource that knows the RepositoryVersion to use to filter its query\n\n    QueryModelResource has-a repository-version that can be used to limit its export, and a\n    queryset that is derived from that repository-version.\n\n    A plugin-writer will subclass their ModelResources from QueryModelResource,\n    and use it to define the limiting query\n\n    Attributes:\n\n        repo_version (models.RepositoryVersion): The RepositoryVersion whose content we would like\n            to export\n        queryset (django.db.models.query.QuerySet): filtering queryset for this resource\n            (driven by repo_version)\n    \"\"\"\n\n    def before_import_row(self, row, **kwargs):\n        \"\"\"\n        Sets pulp_domain/_pulp_domain to the current-domain on import.\n        Args:\n            row (tablib.Dataset row): incoming import-row representing a single Variant.\n            kwargs: args passed along from the import() call.\n        \"\"\"\n        # There is probably a more pythonic/elegant way to do the following - but I am deliberately\n        # opting for \"verbose but COMPLETELY CLEAR\" here.\n        if \"_pulp_domain\" in row:\n            row[\"_pulp_domain\"] = get_domain_pk()\n\n        if \"pulp_domain\" in row:\n            row[\"pulp_domain\"] = get_domain_pk()\n\n    def set_up_queryset(self):\n        return None\n\n    def __init__(self, repo_version=None):\n        self.repo_version = repo_version\n        if repo_version:\n            self.queryset = self.set_up_queryset()\n\n    class Meta:\n        exclude = (\"pulp_id\", \"pulp_created\", \"pulp_last_updated\")\n\n\nclass BaseContentResource(QueryModelResource):\n    \"\"\"\n    A QueryModelResource that knows how to fill in the 'upstream_id' export-field\n\n    BaseContentResource knows to de/hydrate upstream_id with the content-being-exported's pulp_id.\n\n    All Content-based resources being import/exported should subclass from this class.\n    \"\"\"\n\n    # An optional mapping that maps Content to Repositories. Useful when Content is sometimes not\n    # tied directly to a Repository but rather to a subrepo. Formatting:\n    #\n    #     {\"<repo name>\": [\"<content upstream_id>\", \"...\"]}\n    #\n    content_mapping = None\n\n    class Meta:\n        exclude = QueryModelResource.Meta.exclude + (\"_artifacts\", \"content\", \"content_ptr\")\n\n    def dehydrate_upstream_id(self, content):\n        return str(content.pulp_id)\n", "path": "pulpcore/plugin/importexport.py"}]}