Repository: pulp/pulpcore

Issue:
Drop 3.16 from auto-ci-update, add 3.39
[noissue]


Discussion:

Resolving patch:
diff --git a/pulpcore/app/migrations/0001_initial.py b/pulpcore/app/migrations/0001_initial.py
--- a/pulpcore/app/migrations/0001_initial.py
+++ b/pulpcore/app/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.7 on 2019-03-18 19:56
+# Generated by Django 2.2 on 2019-04-22 17:55
 
 from django.conf import settings
 import django.core.validators
@@ -19,8 +19,8 @@ class Migration(migrations.Migration):
     initial = True
 
     dependencies = [
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
         ('contenttypes', '0002_remove_content_type_name'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
     ]
 
     operations = [
@@ -66,6 +66,9 @@ class Migration(migrations.Migration):
                 ('artifact', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='core.Artifact')),
                 ('content', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Content')),
             ],
+            options={
+                'unique_together': {('content', 'relative_path')},
+            },
             bases=(models.Model, pulpcore.app.models.content.QueryMixin),
         ),
         migrations.CreateModel(
@@ -82,33 +85,6 @@ class Migration(migrations.Migration):
                 'abstract': False,
             },
         ),
-        migrations.CreateModel(
-            name='CreatedResource',
-            fields=[
-                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('_created', models.DateTimeField(auto_now_add=True)),
-                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('object_id', models.UUIDField()),
-                ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
-            ],
-            options={
-                'abstract': False,
-            },
-        ),
-        migrations.CreateModel(
-            name='Distribution',
-            fields=[
-                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('_created', models.DateTimeField(auto_now_add=True)),
-                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('name', models.CharField(db_index=True, max_length=255, unique=True)),
-                ('base_path', models.CharField(max_length=255, unique=True)),
-                ('content_guard', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.ContentGuard')),
-            ],
-            options={
-                'default_related_name': '_distributions',
-            },
-        ),
         migrations.CreateModel(
             name='Exporter',
             fields=[
@@ -123,63 +99,6 @@ class Migration(migrations.Migration):
                 'default_related_name': 'exporters',
             },
         ),
-        migrations.CreateModel(
-            name='ProgressReport',
-            fields=[
-                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('_created', models.DateTimeField(auto_now_add=True)),
-                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('message', models.TextField()),
-                ('state', models.TextField(choices=[('waiting', 'Waiting'), ('skipped', 'Skipped'), ('running', 'Running'), ('completed', 'Completed'), ('failed', 'Failed'), ('canceled', 'Canceled')], default='waiting')),
-                ('total', models.IntegerField(null=True)),
-                ('done', models.IntegerField(default=0)),
-                ('suffix', models.TextField(default='')),
-            ],
-            options={
-                'abstract': False,
-            },
-        ),
-        migrations.CreateModel(
-            name='Publication',
-            fields=[
-                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('_created', models.DateTimeField(auto_now_add=True)),
-                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('complete', models.BooleanField(db_index=True, default=False)),
-                ('pass_through', models.BooleanField(default=False)),
-            ],
-            options={
-                'abstract': False,
-            },
-        ),
-        migrations.CreateModel(
-            name='PublishedArtifact',
-            fields=[
-                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('_created', models.DateTimeField(auto_now_add=True)),
-                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('relative_path', models.CharField(max_length=255)),
-                ('content_artifact', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_artifact', to='core.ContentArtifact')),
-                ('publication', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_artifact', to='core.Publication')),
-            ],
-            options={
-                'default_related_name': 'published_artifact',
-            },
-        ),
-        migrations.CreateModel(
-            name='PublishedMetadata',
-            fields=[
-                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('_created', models.DateTimeField(auto_now_add=True)),
-                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('relative_path', models.CharField(max_length=255)),
-                ('file', models.FileField(max_length=255, upload_to=pulpcore.app.models.publication.PublishedMetadata._storage_path)),
-                ('publication', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_metadata', to='core.Publication')),
-            ],
-            options={
-                'default_related_name': 'published_metadata',
-            },
-        ),
         migrations.CreateModel(
             name='Publisher',
             fields=[
@@ -217,25 +136,6 @@ class Migration(migrations.Migration):
                 'default_related_name': 'remotes',
             },
         ),
-        migrations.CreateModel(
-            name='RemoteArtifact',
-            fields=[
-                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('_created', models.DateTimeField(auto_now_add=True)),
-                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('url', models.TextField(validators=[django.core.validators.URLValidator])),
-                ('size', models.IntegerField(null=True)),
-                ('md5', models.CharField(max_length=32, null=True)),
-                ('sha1', models.CharField(max_length=40, null=True)),
-                ('sha224', models.CharField(max_length=56, null=True)),
-                ('sha256', models.CharField(max_length=64, null=True)),
-                ('sha384', models.CharField(max_length=96, null=True)),
-                ('sha512', models.CharField(max_length=128, null=True)),
-                ('content_artifact', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.ContentArtifact')),
-                ('remote', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Remote')),
-            ],
-            bases=(models.Model, pulpcore.app.models.content.QueryMixin),
-        ),
         migrations.CreateModel(
             name='Repository',
             fields=[
@@ -250,16 +150,6 @@ class Migration(migrations.Migration):
                 'verbose_name_plural': 'repositories',
             },
         ),
-        migrations.CreateModel(
-            name='RepositoryContent',
-            fields=[
-                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('_created', models.DateTimeField(auto_now_add=True)),
-                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('content', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='version_memberships', to='core.Content')),
-                ('repository', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Repository')),
-            ],
-        ),
         migrations.CreateModel(
             name='RepositoryVersion',
             fields=[
@@ -275,18 +165,9 @@ class Migration(migrations.Migration):
                 'ordering': ('number',),
                 'get_latest_by': 'number',
                 'default_related_name': 'versions',
+                'unique_together': {('repository', 'number')},
             },
         ),
-        migrations.CreateModel(
-            name='RepositoryVersionContentDetails',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('count_type', models.CharField(choices=[('A', 'added'), ('P', 'present'), ('R', 'removed')], max_length=1)),
-                ('content_type', models.TextField()),
-                ('count', models.IntegerField()),
-                ('repository_version', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='counts', to='core.RepositoryVersion')),
-            ],
-        ),
         migrations.CreateModel(
             name='ReservedResource',
             fields=[
@@ -318,13 +199,15 @@ class Migration(migrations.Migration):
             },
         ),
         migrations.CreateModel(
-            name='TaskReservedResource',
+            name='Worker',
             fields=[
                 ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                 ('_created', models.DateTimeField(auto_now_add=True)),
                 ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.ReservedResource')),
-                ('task', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='core.Task')),
+                ('name', models.CharField(db_index=True, max_length=255, unique=True)),
+                ('last_heartbeat', models.DateTimeField(auto_now=True)),
+                ('gracefully_stopped', models.BooleanField(default=False)),
+                ('cleaned_up', models.BooleanField(default=False)),
             ],
             options={
                 'abstract': False,
@@ -347,15 +230,13 @@ class Migration(migrations.Migration):
             },
         ),
         migrations.CreateModel(
-            name='Worker',
+            name='TaskReservedResource',
             fields=[
                 ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                 ('_created', models.DateTimeField(auto_now_add=True)),
                 ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('name', models.CharField(db_index=True, max_length=255, unique=True)),
-                ('last_heartbeat', models.DateTimeField(auto_now=True)),
-                ('gracefully_stopped', models.BooleanField(default=False)),
-                ('cleaned_up', models.BooleanField(default=False)),
+                ('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.ReservedResource')),
+                ('task', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='core.Task')),
             ],
             options={
                 'abstract': False,
@@ -376,60 +257,100 @@ class Migration(migrations.Migration):
             name='worker',
             field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reservations', to='core.Worker'),
         ),
-        migrations.AddField(
-            model_name='repositorycontent',
-            name='version_added',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='added_memberships', to='core.RepositoryVersion'),
+        migrations.CreateModel(
+            name='RepositoryVersionContentDetails',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('count_type', models.CharField(choices=[('A', 'added'), ('P', 'present'), ('R', 'removed')], max_length=1)),
+                ('content_type', models.TextField()),
+                ('count', models.IntegerField()),
+                ('repository_version', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='counts', to='core.RepositoryVersion')),
+            ],
         ),
-        migrations.AddField(
-            model_name='repositorycontent',
-            name='version_removed',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='removed_memberships', to='core.RepositoryVersion'),
+        migrations.CreateModel(
+            name='RepositoryContent',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('_created', models.DateTimeField(auto_now_add=True)),
+                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('content', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='version_memberships', to='core.Content')),
+                ('repository', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Repository')),
+                ('version_added', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='added_memberships', to='core.RepositoryVersion')),
+                ('version_removed', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='removed_memberships', to='core.RepositoryVersion')),
+            ],
+            options={
+                'unique_together': {('repository', 'content', 'version_added'), ('repository', 'content', 'version_removed')},
+            },
         ),
         migrations.AddField(
             model_name='repository',
             name='content',
             field=models.ManyToManyField(related_name='repositories', through='core.RepositoryContent', to='core.Content'),
         ),
-        migrations.AddField(
-            model_name='publication',
-            name='publisher',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Publisher'),
-        ),
-        migrations.AddField(
-            model_name='publication',
-            name='repository_version',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.RepositoryVersion'),
-        ),
-        migrations.AddField(
-            model_name='progressreport',
-            name='task',
-            field=models.ForeignKey(default=pulpcore.app.models.task.Task.current, on_delete=django.db.models.deletion.CASCADE, related_name='progress_reports', to='core.Task'),
-        ),
-        migrations.AddField(
-            model_name='distribution',
-            name='publication',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Publication'),
-        ),
-        migrations.AddField(
-            model_name='distribution',
-            name='publisher',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Publisher'),
+        migrations.CreateModel(
+            name='Publication',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('_created', models.DateTimeField(auto_now_add=True)),
+                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('_type', models.TextField(default=None)),
+                ('complete', models.BooleanField(db_index=True, default=False)),
+                ('pass_through', models.BooleanField(default=False)),
+                ('publisher', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Publisher')),
+                ('repository_version', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.RepositoryVersion')),
+            ],
+            options={
+                'abstract': False,
+            },
         ),
-        migrations.AddField(
-            model_name='distribution',
-            name='remote',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Remote'),
+        migrations.CreateModel(
+            name='ProgressReport',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('_created', models.DateTimeField(auto_now_add=True)),
+                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('message', models.TextField()),
+                ('state', models.TextField(choices=[('waiting', 'Waiting'), ('skipped', 'Skipped'), ('running', 'Running'), ('completed', 'Completed'), ('failed', 'Failed'), ('canceled', 'Canceled')], default='waiting')),
+                ('total', models.IntegerField(null=True)),
+                ('done', models.IntegerField(default=0)),
+                ('suffix', models.TextField(default='')),
+                ('task', models.ForeignKey(default=pulpcore.app.models.task.Task.current, on_delete=django.db.models.deletion.CASCADE, related_name='progress_reports', to='core.Task')),
+            ],
+            options={
+                'abstract': False,
+            },
         ),
-        migrations.AddField(
-            model_name='distribution',
-            name='repository',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Repository'),
+        migrations.CreateModel(
+            name='Distribution',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('_created', models.DateTimeField(auto_now_add=True)),
+                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('name', models.CharField(db_index=True, max_length=255, unique=True)),
+                ('base_path', models.CharField(max_length=255, unique=True)),
+                ('content_guard', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.ContentGuard')),
+                ('publication', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Publication')),
+                ('publisher', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Publisher')),
+                ('remote', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Remote')),
+                ('repository', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Repository')),
+            ],
+            options={
+                'default_related_name': '_distributions',
+            },
         ),
-        migrations.AddField(
-            model_name='createdresource',
-            name='task',
-            field=models.ForeignKey(default=pulpcore.app.models.task.Task.current, on_delete=django.db.models.deletion.CASCADE, related_name='created_resources', to='core.Task'),
+        migrations.CreateModel(
+            name='CreatedResource',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('_created', models.DateTimeField(auto_now_add=True)),
+                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('object_id', models.UUIDField()),
+                ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
+                ('task', models.ForeignKey(default=pulpcore.app.models.task.Task.current, on_delete=django.db.models.deletion.CASCADE, related_name='created_resources', to='core.Task')),
+            ],
+            options={
+                'abstract': False,
+            },
         ),
         migrations.AddField(
             model_name='content',
@@ -443,6 +364,7 @@ class Migration(migrations.Migration):
             options={
                 'proxy': True,
                 'indexes': [],
+                'constraints': [],
             },
             bases=('core.progressreport',),
         ),
@@ -453,31 +375,60 @@ class Migration(migrations.Migration):
             options={
                 'proxy': True,
                 'indexes': [],
+                'constraints': [],
             },
             bases=('core.progressreport',),
         ),
-        migrations.AlterUniqueTogether(
-            name='repositoryversion',
-            unique_together={('repository', 'number')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='repositorycontent',
-            unique_together={('repository', 'content', 'version_added'), ('repository', 'content', 'version_removed')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='remoteartifact',
-            unique_together={('content_artifact', 'remote')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='publishedmetadata',
-            unique_together={('publication', 'relative_path'), ('publication', 'file')},
+        migrations.CreateModel(
+            name='RemoteArtifact',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('_created', models.DateTimeField(auto_now_add=True)),
+                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('url', models.TextField(validators=[django.core.validators.URLValidator])),
+                ('size', models.IntegerField(null=True)),
+                ('md5', models.CharField(max_length=32, null=True)),
+                ('sha1', models.CharField(max_length=40, null=True)),
+                ('sha224', models.CharField(max_length=56, null=True)),
+                ('sha256', models.CharField(max_length=64, null=True)),
+                ('sha384', models.CharField(max_length=96, null=True)),
+                ('sha512', models.CharField(max_length=128, null=True)),
+                ('content_artifact', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.ContentArtifact')),
+                ('remote', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Remote')),
+            ],
+            options={
+                'unique_together': {('content_artifact', 'remote')},
+            },
+            bases=(models.Model, pulpcore.app.models.content.QueryMixin),
         ),
-        migrations.AlterUniqueTogether(
-            name='publishedartifact',
-            unique_together={('publication', 'content_artifact'), ('publication', 'relative_path')},
+        migrations.CreateModel(
+            name='PublishedMetadata',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('_created', models.DateTimeField(auto_now_add=True)),
+                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('relative_path', models.CharField(max_length=255)),
+                ('file', models.FileField(max_length=255, upload_to=pulpcore.app.models.publication.PublishedMetadata._storage_path)),
+                ('publication', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_metadata', to='core.Publication')),
+            ],
+            options={
+                'default_related_name': 'published_metadata',
+                'unique_together': {('publication', 'relative_path'), ('publication', 'file')},
+            },
         ),
-        migrations.AlterUniqueTogether(
-            name='contentartifact',
-            unique_together={('content', 'relative_path')},
+        migrations.CreateModel(
+            name='PublishedArtifact',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('_created', models.DateTimeField(auto_now_add=True)),
+                ('_last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('relative_path', models.CharField(max_length=255)),
+                ('content_artifact', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_artifact', to='core.ContentArtifact')),
+                ('publication', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='published_artifact', to='core.Publication')),
+            ],
+            options={
+                'default_related_name': 'published_artifact',
+                'unique_together': {('publication', 'relative_path'), ('publication', 'content_artifact')},
+            },
         ),
     ]
diff --git a/pulpcore/app/models/publication.py b/pulpcore/app/models/publication.py
--- a/pulpcore/app/models/publication.py
+++ b/pulpcore/app/models/publication.py
@@ -6,7 +6,7 @@
 from .task import CreatedResource
 
 
-class Publication(Model):
+class Publication(MasterModel):
     """
     A publication contains metadata and artifacts associated with content
     contained within a RepositoryVersion.
@@ -40,6 +40,7 @@ class Publication(Model):
         >>>             ...
         >>>
     """
+    TYPE = 'publication'
 
     complete = models.BooleanField(db_index=True, default=False)
     pass_through = models.BooleanField(default=False)
diff --git a/pulpcore/app/serializers/publication.py b/pulpcore/app/serializers/publication.py
--- a/pulpcore/app/serializers/publication.py
+++ b/pulpcore/app/serializers/publication.py
@@ -19,10 +19,8 @@
 )
 
 
-class PublicationSerializer(ModelSerializer):
-    _href = IdentityField(
-        view_name='publications-detail'
-    )
+class PublicationSerializer(MasterModelSerializer):
+    _href = DetailIdentityField()
     publisher = DetailRelatedField(
         help_text=_('The publisher that created this publication.'),
         queryset=models.Publisher.objects.all()
@@ -42,8 +40,9 @@ class PublicationSerializer(ModelSerializer):
     )
 
     class Meta:
+        abstract = True
         model = models.Publication
-        fields = ModelSerializer.Meta.fields + (
+        fields = MasterModelSerializer.Meta.fields + (
             'publisher',
             '_distributions',
             'repository_version',
@@ -96,11 +95,10 @@ class BaseDistributionSerializer(ModelSerializer):
         queryset=models.ContentGuard.objects.all(),
         allow_null=True
     )
-    publication = RelatedField(
+    publication = DetailRelatedField(
         required=False,
         help_text=_('The publication being served as defined by this distribution'),
         queryset=models.Publication.objects.exclude(complete=False),
-        view_name='publications-detail',
         allow_null=True
     )
     repository = RelatedField(


Test patch:
diff --git a/pulpcore/tests/functional/api/using_plugin/constants.py b/pulpcore/tests/functional/api/using_plugin/constants.py
--- a/pulpcore/tests/functional/api/using_plugin/constants.py
+++ b/pulpcore/tests/functional/api/using_plugin/constants.py
@@ -4,6 +4,7 @@
 
 from pulp_smash.constants import PULP_FIXTURES_BASE_URL
 from pulp_smash.pulp3.constants import (
+    BASE_PUBLICATION_PATH,
     BASE_PUBLISHER_PATH,
     BASE_REMOTE_PATH,
     CONTENT_PATH
@@ -18,6 +19,8 @@
 
 FILE_PUBLISHER_PATH = urljoin(BASE_PUBLISHER_PATH, 'file/file/')
 
+FILE_PUBLICATION_PATH = urljoin(BASE_PUBLICATION_PATH, 'file/file/')
+
 FILE_FIXTURE_URL = urljoin(PULP_FIXTURES_BASE_URL, 'file/')
 """The URL to a file repository."""
 
diff --git a/pulpcore/tests/functional/api/using_plugin/test_crd_publications.py b/pulpcore/tests/functional/api/using_plugin/test_crd_publications.py
--- a/pulpcore/tests/functional/api/using_plugin/test_crd_publications.py
+++ b/pulpcore/tests/functional/api/using_plugin/test_crd_publications.py
@@ -8,7 +8,6 @@
 from pulp_smash import api, config
 from pulp_smash.pulp3.constants import (
     DISTRIBUTION_PATH,
-    PUBLICATIONS_PATH,
     REPO_PATH
 )
 from pulp_smash.pulp3.utils import (
@@ -21,6 +20,7 @@
 
 from pulpcore.tests.functional.api.utils import parse_date_from_string
 from pulpcore.tests.functional.api.using_plugin.constants import (
+    FILE_PUBLICATION_PATH,
     FILE_PUBLISHER_PATH,
     FILE_REMOTE_PATH
 )
@@ -105,7 +105,7 @@ def test_02_read_publication_without_specific_fields(self):
     @skip_if(bool, 'publication', False)
     def test_02_read_publications(self):
         """Read a publication by its repository version."""
-        publications = self.client.get(PUBLICATIONS_PATH, params={
+        publications = self.client.get(FILE_PUBLICATION_PATH, params={
             'repository_version': self.repo['_href']
         })
         self.assertEqual(len(publications), 1, publications)
@@ -116,7 +116,7 @@ def test_02_read_publications(self):
     @skip_if(bool, 'publication', False)
     def test_03_read_publications(self):
         """Read a publication by its publisher."""
-        publications = self.client.get(PUBLICATIONS_PATH, params={
+        publications = self.client.get(FILE_PUBLICATION_PATH, params={
             'publisher': self.publisher['_href']
         })
         self.assertEqual(len(publications), 1, publications)
@@ -127,7 +127,7 @@ def test_03_read_publications(self):
     @skip_if(bool, 'publication', False)
     def test_04_read_publications(self):
         """Read a publication by its created time."""
-        publications = self.client.get(PUBLICATIONS_PATH, params={
+        publications = self.client.get(FILE_PUBLICATION_PATH, params={
             '_created': self.publication['_created']
         })
         self.assertEqual(len(publications), 1, publications)
@@ -146,7 +146,7 @@ def test_05_read_publications(self):
         self.addCleanup(self.client.delete, distribution['_href'])
 
         self.publication.update(self.client.get(self.publication['_href']))
-        publications = self.client.get(PUBLICATIONS_PATH, params={
+        publications = self.client.get(FILE_PUBLICATION_PATH, params={
             'distributions': distribution['_href']
         })
         self.assertEqual(len(publications), 1, publications)
@@ -169,7 +169,7 @@ def test_06_publication_create_order(self):
 
         # Read publications
         publications = self.client.get(
-            PUBLICATIONS_PATH,
+            FILE_PUBLICATION_PATH,
             params={'publisher': self.publisher['_href']}
         )
         self.assertEqual(len(publications), 3)