diff --git a/dje/tests/testfiles/test_dataset_ll_only.json b/dje/tests/testfiles/test_dataset_ll_only.json index ae8f80fe..b3fc3282 100644 --- a/dje/tests/testfiles/test_dataset_ll_only.json +++ b/dje/tests/testfiles/test_dataset_ll_only.json @@ -36,6 +36,7 @@ ], "uuid": "5a4ec739-50be-4744-a7d6-4ba36f9ba4cd", "name": "1: LicenseProfile1", + "default_usage_policy": null, "examples": "", "notes": "" } diff --git a/license_library/admin.py b/license_library/admin.py index 6df8211c..95af2f4a 100644 --- a/license_library/admin.py +++ b/license_library/admin.py @@ -357,11 +357,15 @@ def set_assigned_tags_from_license_profile(self, request, obj): self.message_user(request, msg) def save_model(self, request, obj, form, change): + # Needs to be set before the `save_model` method call. + if obj.license_profile: + obj.set_usage_policy_from_license_profile() + if change: obj_before_save = License.objects.get(id=obj.id) super().save_model(request, obj, form, change) # If a LicenseProfile is set or changed, apply the values of the - # this Profile to the license assigned tags. + # Profile to the license assigned tags. if obj.license_profile and obj.license_profile != obj_before_save.license_profile: self.set_assigned_tags_from_license_profile(request, obj) else: @@ -452,7 +456,7 @@ class LicenseTagHolderBaseAdmin(DataspacedAdmin): The purpose of this class is to be extended by LicenseProfileAdmin and LicenseTagGroupAdmin. It's used to add a LicenseTag queryset in the context of the add and changes views, to display special data (added through - javascript) about tags in the page like text and guidance information. + avascript) about tags in the page like text and guidance information. """ change_form_template = "admin/license_library/tag_holder/change_form.html" @@ -519,11 +523,12 @@ class LicenseProfileAdmin(LicenseTagHolderBaseAdmin): "name", "get_assigned_tags_html", "examples", + "default_usage_policy", "get_dataspace", ) fieldsets = ( ("", {"fields": ("name",)}), - ("", {"fields": ("examples", "notes", "dataspace", "uuid")}), + ("", {"fields": ("examples", "notes", "default_usage_policy", "dataspace", "uuid")}), ) search_fields = ("name",) list_filter = DataspacedAdmin.list_filter + (ReportingQueryListFilter,) @@ -553,10 +558,6 @@ class LicenseProfileAdmin(LicenseTagHolderBaseAdmin): will be Unknown.", ) - def get_queryset(self, request): - qs = super().get_queryset(request) - return qs.prefetch_related("licenseprofileassignedtag_set__license_tag") - @admin.register(LicenseCategory, site=dejacode_site) class LicenseCategoryAdmin(DataspacedAdmin): diff --git a/license_library/migrations/0003_licenseprofile_default_usage_policy.py b/license_library/migrations/0003_licenseprofile_default_usage_policy.py new file mode 100644 index 00000000..07454ea2 --- /dev/null +++ b/license_library/migrations/0003_licenseprofile_default_usage_policy.py @@ -0,0 +1,20 @@ +# Generated by Django 5.2.9 on 2026-02-09 02:10 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('license_library', '0002_initial'), + ('policy', '0002_initial'), + ] + + operations = [ + migrations.AddField( + model_name='licenseprofile', + name='default_usage_policy', + field=models.ForeignKey(blank=True, help_text='Default usage policy to be assigned to a license when using this license profile.', limit_choices_to={'content_type__app_label': 'license_library', 'content_type__model': 'license'}, null=True, on_delete=django.db.models.deletion.SET_NULL, to='policy.usagepolicy'), + ), + ] diff --git a/license_library/models.py b/license_library/models.py index 1354ba21..75590aeb 100644 --- a/license_library/models.py +++ b/license_library/models.py @@ -209,6 +209,20 @@ class LicenseProfile(DataspacedModel): ), ) + default_usage_policy = models.ForeignKey( + to="policy.UsagePolicy", + limit_choices_to={ + "content_type__app_label": "license_library", + "content_type__model": "license", + }, + null=True, + blank=True, + on_delete=models.SET_NULL, + help_text=_( + "Default usage policy to be assigned to a license when using this license profile." + ), + ) + class Meta: unique_together = (("dataspace", "name"), ("dataspace", "uuid")) ordering = ["name"] @@ -986,6 +1000,20 @@ def set_assigned_tags_from_license_profile(self): defaults={"value": profile_assigned_tag.value}, ) + def set_usage_policy_from_license_profile(self): + """ + Set default usage_policy value from the license_profile + when usage_policy is not already defined. + """ + apply_default_usage_policy = ( + not self.usage_policy + and self.license_profile + and self.license_profile.default_usage_policy + ) + + if apply_default_usage_policy: + self.usage_policy = self.license_profile.default_usage_policy + @staticmethod def get_extra_relational_fields(): return ["annotations", "external_references"] diff --git a/license_library/tests/test_models.py b/license_library/tests/test_models.py index cdfa91ed..93f8ff11 100644 --- a/license_library/tests/test_models.py +++ b/license_library/tests/test_models.py @@ -28,6 +28,7 @@ from license_library.models import LicenseTagGroup from license_library.models import LicenseTagGroupAssignedTag from organization.models import Owner +from policy.tests import make_usage_policy from product_portfolio.models import Product @@ -304,6 +305,20 @@ def test_license_model_data_for_expression_builder(self): data_for_expression_builder = License.objects.all().data_for_expression_builder() self.assertEqual(expected, data_for_expression_builder) + def test_license_model_set_usage_policy_from_license_profile(self): + self.license1.set_usage_policy_from_license_profile() + self.assertIsNone(self.license1.usage_policy) + + self.license1.update(license_profile=self.license_profile) + self.license1.set_usage_policy_from_license_profile() + self.assertIsNone(self.license1.usage_policy) + + license_policy = make_usage_policy(self.dataspace, model=License) + self.license_profile.update(default_usage_policy=license_policy) + + self.license1.set_usage_policy_from_license_profile() + self.assertEqual(license_policy, self.license1.usage_policy) + def test_license_library_models_get_exclude_candidates_fields(self): input_data = ( ( @@ -355,6 +370,7 @@ def test_license_library_models_get_exclude_candidates_fields(self): ( LicenseProfile, [ + "default_usage_policy", "examples", "notes", ],