diff --git a/admin/cedar/forms.py b/admin/cedar/forms.py
index f2eb43c6a9b..e446dde4196 100644
--- a/admin/cedar/forms.py
+++ b/admin/cedar/forms.py
@@ -1,7 +1,8 @@
-from django.forms import ModelForm, CharField, JSONField
+from django.forms import ModelForm, CharField, JSONField, BooleanField
from osf.models import CedarMetadataTemplate
+
class CedarMetadataTemplateForm(ModelForm):
schema_name = CharField(
disabled=True,
@@ -18,7 +19,8 @@ class CedarMetadataTemplateForm(ModelForm):
template = JSONField(
disabled=True
)
+ is_for_collections = BooleanField(label='For collections only:', required=False)
class Meta:
model = CedarMetadataTemplate
- fields = ['schema_name', 'cedar_id', 'template_version', 'template', 'active', 'should_index_for_search']
+ fields = ['schema_name', 'cedar_id', 'template_version', 'template', 'is_for_collections', 'active', 'should_index_for_search']
diff --git a/admin/templates/cedar/list.html b/admin/templates/cedar/list.html
index 9d089714e50..0717d1c342b 100644
--- a/admin/templates/cedar/list.html
+++ b/admin/templates/cedar/list.html
@@ -14,6 +14,7 @@
List of Cedar Metadata Templates
Name |
Version |
Active |
+ For Collections only |
@@ -33,6 +34,9 @@ List of Cedar Metadata Templates
{{ template.active }}
|
+
+ {{ template.is_for_collections }}
+ |
{% endfor %}
diff --git a/api/cedar_metadata_templates/serializers.py b/api/cedar_metadata_templates/serializers.py
index dd3570f9c79..f2463e8a648 100644
--- a/api/cedar_metadata_templates/serializers.py
+++ b/api/cedar_metadata_templates/serializers.py
@@ -9,7 +9,7 @@ class CedarMetadataTemplateSerializer(JSONAPISerializer):
class Meta:
type_ = 'cedar-metadata-templates'
- filterable_fields = frozenset(['schema_name', 'cedar_id', 'active'])
+ filterable_fields = frozenset(['schema_name', 'cedar_id', 'active', 'is_for_collections'])
id = ser.CharField(source='_id', read_only=True)
schema_name = ser.CharField(read_only=True)
@@ -17,6 +17,7 @@ class Meta:
template = ser.DictField(read_only=True)
active = ser.BooleanField(read_only=True)
template_version = ser.IntegerField(read_only=True)
+ is_for_collections = ser.BooleanField(read_only=True)
links = LinksField({'self': 'get_absolute_url'})
diff --git a/api_tests/cedar_metadata_templates/views/test_template.py b/api_tests/cedar_metadata_templates/views/test_template.py
index 36a59117fc0..d154c70730b 100644
--- a/api_tests/cedar_metadata_templates/views/test_template.py
+++ b/api_tests/cedar_metadata_templates/views/test_template.py
@@ -30,8 +30,19 @@ def active_template_alt(self):
)
@pytest.fixture()
- def active_template_ids(self, active_template, active_template_alt):
- return [active_template._id, active_template_alt._id]
+ def active_template_for_collections(self):
+ return CedarMetadataTemplate.objects.create(
+ schema_name=fake.bs(),
+ cedar_id=fake.md5(),
+ template_version=1,
+ template={},
+ active=True,
+ is_for_collections=True
+ )
+
+ @pytest.fixture()
+ def active_template_ids(self, active_template, active_template_alt, active_template_for_collections):
+ return [active_template._id, active_template_alt._id, active_template_for_collections._id]
@pytest.fixture()
def inactive_template(self):
diff --git a/api_tests/cedar_metadata_templates/views/test_template_list.py b/api_tests/cedar_metadata_templates/views/test_template_list.py
index 512ee84a03f..f4bbc6cd513 100644
--- a/api_tests/cedar_metadata_templates/views/test_template_list.py
+++ b/api_tests/cedar_metadata_templates/views/test_template_list.py
@@ -11,5 +11,19 @@ def test_template_list(self, app, active_template_ids):
resp = app.get('/_/cedar_metadata_templates/')
assert resp.status_code == 200
data = resp.json['data']
- assert len(data) == 2
+ assert len(data) == 3
assert set(active_template_ids) == {datum['id'] for datum in data}
+
+ def test_filter_templates_for_collections_only(self, app, active_template_for_collections, active_template_ids):
+ resp = app.get('/_/cedar_metadata_templates/?filter[is_for_collections]=true')
+ assert resp.status_code == 200
+ data = resp.json['data']
+ assert len(data) == 1
+ assert data[0]['id'] == active_template_for_collections._id
+
+ resp = app.get('/_/cedar_metadata_templates/?filter[is_for_collections]=false')
+ assert resp.status_code == 200
+ data = resp.json['data']
+ assert len(data) == 2
+ for template in data:
+ assert template['id'] != active_template_for_collections._id
diff --git a/osf/migrations/0042_cedarmetadatatemplate_is_for_collections.py b/osf/migrations/0042_cedarmetadatatemplate_is_for_collections.py
new file mode 100644
index 00000000000..f793a8f71aa
--- /dev/null
+++ b/osf/migrations/0042_cedarmetadatatemplate_is_for_collections.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.26 on 2026-05-28 07:13
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('osf', '0041_cedarmetadatatemplate_should_index_for_search'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='cedarmetadatatemplate',
+ name='is_for_collections',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/osf/models/cedar_metadata.py b/osf/models/cedar_metadata.py
index df8d4cda4d3..b062f38128e 100644
--- a/osf/models/cedar_metadata.py
+++ b/osf/models/cedar_metadata.py
@@ -11,6 +11,7 @@ class CedarMetadataTemplate(ObjectIDMixin, BaseModel):
active = models.BooleanField(default=True)
template_version = models.PositiveIntegerField()
should_index_for_search = models.BooleanField(default=False)
+ is_for_collections = models.BooleanField(default=False)
class Meta:
unique_together = ('cedar_id', 'template_version')