diff --git a/django/cantusdb_project/main_app/forms.py b/django/cantusdb_project/main_app/forms.py index 4f65fa883..698cc8359 100644 --- a/django/cantusdb_project/main_app/forms.py +++ b/django/cantusdb_project/main_app/forms.py @@ -71,6 +71,15 @@ def label_from_instance(self, obj): widget = CheckboxSelectMultiple() +class StyledChoiceField(forms.ChoiceField): + """ + A custom ChoiceField that uses the custom SelectWidget defined in widgets.py + as its widget (for styling). + """ + + widget = SelectWidget() + + class ChantCreateForm(forms.ModelForm): class Meta: model = Chant @@ -191,6 +200,7 @@ class Meta: # "siglum", "holding_institution", "shelfmark", + "name", "segment_m2m", "provenance", "provenance_notes", @@ -212,11 +222,15 @@ class Meta: "fragmentarium_id", "dact_id", "indexing_notes", + "production_method", + "source_completeness", ] widgets = { # "title": TextInputWidget(), # "siglum": TextInputWidget(), + "shelfmark": TextInputWidget(), "provenance": autocomplete.ModelSelect2(url="provenance-autocomplete"), + "name": TextInputWidget(), "provenance_notes": TextInputWidget(), "date": TextInputWidget(), "cursus": SelectWidget(), @@ -246,6 +260,8 @@ class Meta: "other_editors": autocomplete.ModelSelect2Multiple( url="all-users-autocomplete" ), + "production_method": SelectWidget(), + "source_completeness": SelectWidget(), } field_classes = { "segment_m2m": CheckboxNameModelMultipleChoiceField, @@ -253,32 +269,15 @@ class Meta: holding_institution = forms.ModelChoiceField( queryset=Institution.objects.all(), - required=True, widget=autocomplete.ModelSelect2(url="holding-autocomplete"), + required=False, ) - shelfmark = forms.CharField( - required=True, - widget=TextInputWidget, - ) - - TRUE_FALSE_CHOICES_SOURCE = ( - (True, "Full source"), - (False, "Fragment or Fragmented"), - ) - - full_source = forms.ChoiceField(choices=TRUE_FALSE_CHOICES_SOURCE, required=False) - full_source.widget.attrs.update( - {"class": "form-control custom-select custom-select-sm"} - ) TRUE_FALSE_CHOICES_INVEN = ((True, "Complete"), (False, "Incomplete")) - complete_inventory = forms.ChoiceField( + complete_inventory = StyledChoiceField( choices=TRUE_FALSE_CHOICES_INVEN, required=False ) - complete_inventory.widget.attrs.update( - {"class": "form-control custom-select custom-select-sm"} - ) class ChantEditForm(forms.ModelForm): @@ -391,6 +390,7 @@ class Meta: # "siglum", "holding_institution", "shelfmark", + "name", "segment_m2m", "provenance", "provenance_notes", @@ -413,12 +413,17 @@ class Meta: "full_text_entered_by", "proofreaders", "other_editors", + "production_method", + "source_completeness", ] widgets = { + "shelfmark": TextInputWidget(), "segment_m2m": CheckboxSelectMultiple(), + "name": TextInputWidget(), "provenance": autocomplete.ModelSelect2(url="provenance-autocomplete"), "provenance_notes": TextInputWidget(), "date": TextInputWidget(), + "cursus": SelectWidget(), "summary": TextAreaWidget(), "liturgical_occasions": TextAreaWidget(), "description": TextAreaWidget(), @@ -446,48 +451,24 @@ class Meta: "other_editors": autocomplete.ModelSelect2Multiple( url="all-users-autocomplete" ), + "production_method": SelectWidget(), + "source_completeness": SelectWidget(), } field_classes = { "segment_m2m": CheckboxNameModelMultipleChoiceField, } - shelfmark = forms.CharField( - required=True, - widget=TextInputWidget, - ) - holding_institution = forms.ModelChoiceField( queryset=Institution.objects.all(), - required=True, widget=autocomplete.ModelSelect2(url="holding-autocomplete"), + required=False, ) - CHOICES_FULL_SOURCE = ( - (None, "None"), - (True, "Full source"), - (False, "Fragment or Fragmented"), - ) - full_source = forms.ChoiceField(choices=CHOICES_FULL_SOURCE, required=False) - full_source.widget.attrs.update( - {"class": "form-control custom-select custom-select-sm"} - ) - - CHOICES_CURSUS = ( - (None, "None"), - ("Monastic", "Monastic"), - ("Secular", "Secular"), - ) - cursus = forms.ChoiceField(choices=CHOICES_CURSUS, required=False) - cursus.widget.attrs.update({"class": "form-control custom-select custom-select-sm"}) - CHOICES_COMPLETE_INV = ( (True, "complete inventory"), (False, "partial inventory"), ) - complete_inventory = forms.ChoiceField(choices=CHOICES_COMPLETE_INV, required=False) - complete_inventory.widget.attrs.update( - {"class": "form-control custom-select custom-select-sm"} - ) + complete_inventory = StyledChoiceField(choices=CHOICES_COMPLETE_INV, required=False) class SequenceEditForm(forms.ModelForm): @@ -733,19 +714,9 @@ class Meta: # help_text="RISM-style siglum + Shelf-mark (e.g. GB-Ob 202).", # ) - shelfmark = forms.CharField( - required=True, - widget=TextInputWidget, - ) - - name = forms.CharField( - required=False, - widget=TextInputWidget - ) - holding_institution = forms.ModelChoiceField( - queryset=Institution.objects.all().order_by("name"), - required=True, + queryset=Institution.objects.all().order_by("city", "name"), + required=False, ) provenance = forms.ModelChoiceField( diff --git a/django/cantusdb_project/main_app/management/commands/migrate_records.py b/django/cantusdb_project/main_app/management/commands/migrate_records.py index bfda4e0a6..bc3f26325 100644 --- a/django/cantusdb_project/main_app/management/commands/migrate_records.py +++ b/django/cantusdb_project/main_app/management/commands/migrate_records.py @@ -163,7 +163,7 @@ def handle(self, *args, **options): ) ) institution = print_inst - elif siglum in created_institutions: + elif siglum in created_institutions and source.id not in bad_siglum: print( self.style.SUCCESS( f"Re-using the pre-created institution for {siglum}" @@ -185,7 +185,7 @@ def handle(self, *args, **options): institution.alternate_names = "\n".join(list(deduped_names)) institution.save() - elif siglum not in created_institutions: + elif siglum not in created_institutions and source.id not in bad_siglum: print(self.style.SUCCESS(f"Creating institution record for {siglum}")) iobj = { @@ -229,6 +229,8 @@ def handle(self, *args, **options): created_institutions[siglum] = institution else: + source.shelfmark = shelfmark.strip() + source.save() print( self.style.ERROR( f"Could not determine the holding institution for {source}" diff --git a/django/cantusdb_project/main_app/management/commands/populate_source_completeness.py b/django/cantusdb_project/main_app/management/commands/populate_source_completeness.py new file mode 100644 index 000000000..fe7d9e279 --- /dev/null +++ b/django/cantusdb_project/main_app/management/commands/populate_source_completeness.py @@ -0,0 +1,22 @@ +""" +A temporary command to populate the source_completeness field in the Source model, +based on the full_source field. This command will be removed once the source_completeness +is initially populated. +""" + +from django.core.management.base import BaseCommand +from main_app.models import Source + + +class Command(BaseCommand): + def handle(self, *args, **options): + sources = Source.objects.all() + for source in sources: + if source.full_source: + source.source_completeness = ( + source.SourceCompletenessChoices.FULL_SOURCE + ) + else: + source.source_completeness = source.SourceCompletenessChoices.FRAGMENT + source.save() + self.stdout.write(self.style.SUCCESS("Source completeness populated")) diff --git a/django/cantusdb_project/main_app/migrations/0031_alter_source_holding_institution_and_more.py b/django/cantusdb_project/main_app/migrations/0031_alter_source_holding_institution_and_more.py deleted file mode 100644 index e793e3991..000000000 --- a/django/cantusdb_project/main_app/migrations/0031_alter_source_holding_institution_and_more.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 4.2.14 on 2024-08-30 13:58 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("main_app", "0030_institution_is_private_collection"), - ] - - operations = [ - migrations.AlterField( - model_name="source", - name="holding_institution", - field=models.ForeignKey( - default=19, - on_delete=django.db.models.deletion.PROTECT, - to="main_app.institution", - ), - preserve_default=False, - ), - migrations.AlterField( - model_name="source", - name="shelfmark", - field=models.CharField( - default="XX-NN", - max_length=255, - ), - ), - ] diff --git a/django/cantusdb_project/main_app/migrations/0031_source_name_source_production_method_and_more.py b/django/cantusdb_project/main_app/migrations/0031_source_name_source_production_method_and_more.py new file mode 100644 index 000000000..b0440b7f8 --- /dev/null +++ b/django/cantusdb_project/main_app/migrations/0031_source_name_source_production_method_and_more.py @@ -0,0 +1,104 @@ +# Generated by Django 4.2.14 on 2024-10-02 17:01 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("main_app", "0030_institution_is_private_collection"), + ] + + operations = [ + migrations.AddField( + model_name="source", + name="name", + field=models.CharField( + blank=True, + help_text="A colloquial or commonly-used name for the source", + max_length=255, + null=True, + ), + ), + migrations.AddField( + model_name="source", + name="production_method", + field=models.IntegerField( + choices=[(1, "Manuscript"), (2, "Printed")], + default=1, + verbose_name="Manuscript/Printed", + ), + ), + migrations.AddField( + model_name="source", + name="source_completeness", + field=models.IntegerField( + choices=[ + (1, "Full source"), + (2, "Fragment/Fragmented"), + (3, "Reconstruction"), + ], + default=1, + verbose_name="Full Source/Fragment", + ), + ), + migrations.AlterField( + model_name="institution", + name="country", + field=models.CharField(default="[No Country]", max_length=64), + ), + migrations.AlterField( + model_name="institution", + name="name", + field=models.CharField(default="[No Name]", max_length=255), + ), + migrations.AlterField( + model_name="source", + name="shelfmark", + field=models.CharField( + default="[No Shelfmark]", + help_text="Primary Cantus Database identifier for the source (e.g. library shelfmark, DACT ID, etc.)", + max_length=255, + ), + ), + migrations.CreateModel( + name="SourceIdentifier", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("identifier", models.CharField(max_length=255)), + ( + "type", + models.IntegerField( + choices=[ + (1, "Other catalogues"), + (2, "olim (Former shelfmark)"), + (3, "Alternative names"), + (4, "RISM Online"), + ] + ), + ), + ("note", models.TextField(blank=True, null=True)), + ( + "source", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="identifiers", + to="main_app.source", + ), + ), + ], + options={ + "verbose_name": "Source Identifier", + "ordering": ("type",), + }, + ), + ] diff --git a/django/cantusdb_project/main_app/migrations/0032_source_name_alter_source_shelfmark.py b/django/cantusdb_project/main_app/migrations/0032_source_name_alter_source_shelfmark.py deleted file mode 100644 index 12a3e2327..000000000 --- a/django/cantusdb_project/main_app/migrations/0032_source_name_alter_source_shelfmark.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 4.2.14 on 2024-09-13 14:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("main_app", "0031_alter_source_holding_institution_and_more"), - ] - - operations = [ - migrations.AddField( - model_name="source", - name="name", - field=models.CharField( - blank=True, - help_text="A colloquial or commonly-used name for the source", - max_length=255, - null=True, - ), - ), - migrations.AlterField( - model_name="source", - name="shelfmark", - field=models.CharField(max_length=255), - ), - ] diff --git a/django/cantusdb_project/main_app/migrations/0033_sourceidentifier.py b/django/cantusdb_project/main_app/migrations/0033_sourceidentifier.py deleted file mode 100644 index d17e23cb0..000000000 --- a/django/cantusdb_project/main_app/migrations/0033_sourceidentifier.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 4.2.14 on 2024-09-13 14:34 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("main_app", "0032_source_name_alter_source_shelfmark"), - ] - - operations = [ - migrations.CreateModel( - name="SourceIdentifier", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("identifier", models.CharField(max_length=255)), - ( - "type", - models.IntegerField( - choices=[ - (1, "Other catalogues"), - (2, "olim (Former shelfmark)"), - (3, "Alternative names"), - (4, "RISM Online"), - ] - ), - ), - ("note", models.TextField(blank=True, null=True)), - ( - "source", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="identifiers", - to="main_app.source", - ), - ), - ], - options={ - "verbose_name": "Source Identifier", - "ordering": ("type",), - }, - ), - ] diff --git a/django/cantusdb_project/main_app/models/institution.py b/django/cantusdb_project/main_app/models/institution.py index e38450d90..a5d966f1b 100644 --- a/django/cantusdb_project/main_app/models/institution.py +++ b/django/cantusdb_project/main_app/models/institution.py @@ -28,7 +28,7 @@ class Meta: ), ] - name = models.CharField(max_length=255, default="s.n.") + name = models.CharField(max_length=255, default="[No Name]") siglum = models.CharField( verbose_name="RISM Siglum", max_length=32, @@ -50,7 +50,7 @@ class Meta: region = models.CharField( max_length=64, blank=True, null=True, help_text=region_help_text ) - country = models.CharField(max_length=64, default="s.l.") + country = models.CharField(max_length=64, default="[No Country]") alternate_names = models.TextField( blank=True, null=True, help_text="Enter alternate names on separate lines." ) diff --git a/django/cantusdb_project/main_app/models/source.py b/django/cantusdb_project/main_app/models/source.py index 98caddc06..2887b95f6 100644 --- a/django/cantusdb_project/main_app/models/source.py +++ b/django/cantusdb_project/main_app/models/source.py @@ -42,19 +42,24 @@ class Source(BaseModel): holding_institution = models.ForeignKey( "Institution", on_delete=models.PROTECT, - null=False, - blank=False, + null=True, + blank=True, ) shelfmark = models.CharField( max_length=255, blank=False, null=False, + help_text=( + "Primary Cantus Database identifier for the source " + "(e.g. library shelfmark, DACT ID, etc.)" + ), + default="[No Shelfmark]", ) name = models.CharField( max_length=255, blank=True, null=True, - help_text="A colloquial or commonly-used name for the source" + help_text="A colloquial or commonly-used name for the source", ) provenance = models.ForeignKey( "Provenance", @@ -71,6 +76,18 @@ class Source(BaseModel): null=True, help_text="More exact indication of the provenance (if necessary)", ) + + class SourceCompletenessChoices(models.IntegerChoices): + FULL_SOURCE = 1, "Full source" + FRAGMENT = 2, "Fragment/Fragmented" + RECONSTRUCTION = 3, "Reconstruction" + + source_completeness = models.IntegerField( + choices=SourceCompletenessChoices.choices, + default=SourceCompletenessChoices.FULL_SOURCE, + verbose_name="Full Source/Fragment", + ) + full_source = models.BooleanField(blank=True, null=True) date = models.CharField( blank=True, @@ -140,6 +157,16 @@ class Source(BaseModel): blank=False, null=False, default=False ) + class ProductionMethodChoices(models.IntegerChoices): + MANUSCRIPT = 1, "Manuscript" + PRINTED = 2, "Printed" + + production_method = models.IntegerField( + default=ProductionMethodChoices.MANUSCRIPT, + choices=ProductionMethodChoices.choices, + verbose_name="Manuscript/Printed", + ) + # number_of_chants and number_of_melodies are used for rendering the source-list page (perhaps among other places) # they are automatically recalculated in main_app.signals.update_source_chant_count and # main_app.signals.update_source_melody_count every time a chant or sequence is saved or deleted @@ -163,10 +190,16 @@ def heading(self) -> str: city = f"{holdinst.city}," if holdinst.city else "" title.append(city) title.append(f"{holdinst.name},") + else: + title.append("Cantus") + + title.append(self.shelfmark) - tt = self.shelfmark if self.shelfmark else self.title + if self.source_completeness == self.SourceCompletenessChoices.FRAGMENT: + title.append("(fragment)") - title.append(tt) + if self.name: + title.append(f'("{self.name}")') return " ".join(title) @@ -176,13 +209,14 @@ def short_heading(self) -> str: if holdinst := self.holding_institution: if holdinst.siglum and holdinst.siglum != "XX-NN": title.append(f"{holdinst.siglum}") - elif holdinst.is_private_collector: + else: title.append("Cantus") + else: + title.append("Cantus") - tt = self.shelfmark if self.shelfmark else self.title - title.append(tt) + title.append(self.shelfmark) - if not self.full_source: + if self.source_completeness == self.SourceCompletenessChoices.FRAGMENT: title.append("(fragment)") return " ".join(title) diff --git a/django/cantusdb_project/main_app/templates/source_create.html b/django/cantusdb_project/main_app/templates/source_create.html index 62a8d50a3..395a373fa 100644 --- a/django/cantusdb_project/main_app/templates/source_create.html +++ b/django/cantusdb_project/main_app/templates/source_create.html @@ -46,12 +46,9 @@

Create Source

{{ form.holding_institution }} -

- {{ form.holding_institution.help_text }} -

@@ -60,8 +57,17 @@

Create Source

Shelfmark:* {{ form.shelfmark }} -

- {{ form.shelfmark.help_text }} +

+ {{ form.shelfmark.help_text|safe }} +

+
+
+ + {{ form.name }} +

+ {{ form.name.help_text|safe }}

@@ -89,19 +95,20 @@

Create Source

- - {{ form.full_source }} -

{{ form.full_source.help_text }}

+ {{ form.source_completeness.label_tag }} + {{ form.source_completeness }}
-
+
{{ form.century.label_tag }} {{ form.century }}
+
+ {{ form.production_method.label_tag }} + {{ form.production_method }} +
diff --git a/django/cantusdb_project/main_app/templates/source_detail.html b/django/cantusdb_project/main_app/templates/source_detail.html index a7eab6478..60e84a39d 100644 --- a/django/cantusdb_project/main_app/templates/source_detail.html +++ b/django/cantusdb_project/main_app/templates/source_detail.html @@ -34,15 +34,20 @@

{{ source.heading }}

{% endif %}
+
Cantus Siglum
+
{{ source.short_heading }}
{% if source.holding_institution %} -
Cantus Siglum
-
{{ source.short_heading }}
Holding Institution
{{ source.holding_institution }}
{% endif %} + {% if source.production_method %} +
Manuscript/Printed
+
{{ source.get_production_method_display }}
+ {% endif %} + {% if source.summary %}
Summary
{{ source.summary }}
@@ -112,10 +117,8 @@

{{ source.heading }}

{{ source.complete_inventory|yesno:"Complete Inventory,Partial Inventory" }}
{% endif %} - {% if source.full_source is not None %} -
Full Source/Fragment
-
{{ source.full_source|yesno:"Full Source,Fragment or Fragmented" }}
- {% endif %} +
Full Source/Fragment
+
{{ source.get_source_completeness_display }}
{% if user.is_authenticated %}
Source Status
diff --git a/django/cantusdb_project/main_app/templates/source_edit.html b/django/cantusdb_project/main_app/templates/source_edit.html index 89d876b07..385ebc1e9 100644 --- a/django/cantusdb_project/main_app/templates/source_edit.html +++ b/django/cantusdb_project/main_app/templates/source_edit.html @@ -48,11 +48,11 @@

{{ form.holding_institution }} -

- {{ form.holding_institution.help_text }} +

+ {{ form.holding_institution.help_text }}

@@ -62,8 +62,17 @@

Shelfmark:* {{ form.shelfmark }} -

- {{ form.shelfmark.help_text }} +

+ {{ form.shelfmark.help_text }} +

+

+
+ + {{ form.name }} +

+ {{ form.name.help_text|safe }}

@@ -90,18 +99,20 @@

More exact indication of the provenance (if necessary)

- - {{ form.full_source }} + {{ form.source_completeness.label_tag }} + {{ form.source_completeness }}
-
+
{{ form.century.label_tag }} {{ form.century }}
+
+ {{ form.production_method.label_tag }} + {{ form.production_method }} +
diff --git a/django/cantusdb_project/main_app/templates/source_list.html b/django/cantusdb_project/main_app/templates/source_list.html index c3cff7bfd..330f48e82 100644 --- a/django/cantusdb_project/main_app/templates/source_list.html +++ b/django/cantusdb_project/main_app/templates/source_list.html @@ -103,9 +103,16 @@

Browse Sources

{{ source.holding_institution.country }} - - {{ source.holding_institution.city }}, {{ source.holding_institution.name }} - + {% if source.holding_institution %} + + + {% if source.holding_institution.city %} + {{ source.holding_institution.city }}, + {% endif %} + {{ source.holding_institution.name }} + + + {% endif %} @@ -113,6 +120,9 @@

Browse Sources

+ {% if source.name %} + "{{ source.name }}"
+ {% endif %} {{ source.summary|default:""|truncatechars_html:120 }} diff --git a/django/cantusdb_project/main_app/tests/make_fakes.py b/django/cantusdb_project/main_app/tests/make_fakes.py index a2febbdbd..5991df946 100644 --- a/django/cantusdb_project/main_app/tests/make_fakes.py +++ b/django/cantusdb_project/main_app/tests/make_fakes.py @@ -362,15 +362,33 @@ def make_fake_institution( city: Optional[str] = None, region: Optional[str] = None, country: Optional[str] = None, + is_private_collector: Optional[bool] = None, ) -> Institution: + """ + Note that the siglum and is_private_collector fields + are mutually exclusive. If both are specified, an exception + will be raised. If neither are specified, the function will + randomly determine whether the institution is a private collector or + will be given a fake siglum. + """ name = name if name else faker.sentence() - siglum = siglum if siglum else faker.sentence(nb_words=1) city = city if city else faker.city() region = region if region else faker.country() country = country if country else faker.country() + if siglum and is_private_collector: + raise ValueError("Siglum and Private Collector cannot both be specified.") + is_private_collector = False if siglum else faker.boolean(chance_of_getting_true=20) + if not is_private_collector and not siglum: + siglum = faker.sentence(nb_words=1) + inst = Institution.objects.create( - name=name, siglum=siglum, city=city, region=region, country=country + name=name, + siglum=siglum, + city=city, + region=region, + country=country, + is_private_collector=is_private_collector, ) inst.save() @@ -468,4 +486,4 @@ def get_random_search_term(target): slice_start = random.randint(0, len(target) - 2) slice_end = random.randint(slice_start + 2, len(target)) search_term = target[slice_start:slice_end] - return search_term \ No newline at end of file + return search_term diff --git a/django/cantusdb_project/main_app/tests/test_populate_source_completeness.py b/django/cantusdb_project/main_app/tests/test_populate_source_completeness.py new file mode 100644 index 000000000..065bbb2ea --- /dev/null +++ b/django/cantusdb_project/main_app/tests/test_populate_source_completeness.py @@ -0,0 +1,29 @@ +from django.test import TestCase +from django.core.management import call_command + +from main_app.models import Source +from main_app.tests.make_fakes import make_fake_source + + +class TestPopulateSourceCompleteness(TestCase): + def test_populate_source_completeness(self): + # make a few "Full Source" sources + for _ in range(5): + make_fake_source(full_source=True) + # make a few "Fragment" sources + for _ in range(3): + make_fake_source(full_source=False) + # run the command + call_command("populate_source_completeness") + sources = Source.objects.all() + for source in sources: + if source.full_source: + self.assertEqual( + source.source_completeness, + source.SourceCompletenessChoices.FULL_SOURCE, + ) + else: + self.assertEqual( + source.source_completeness, + source.SourceCompletenessChoices.FRAGMENT, + ) diff --git a/django/cantusdb_project/main_app/tests/test_views/test_source.py b/django/cantusdb_project/main_app/tests/test_views/test_source.py index e7102d4ec..8c9e529a5 100644 --- a/django/cantusdb_project/main_app/tests/test_views/test_source.py +++ b/django/cantusdb_project/main_app/tests/test_views/test_source.py @@ -54,15 +54,14 @@ def test_url_and_templates(self): self.assertTemplateUsed(response, "source_create.html") def test_create_source(self): - hinst = make_fake_institution(siglum="FA-Ke") response = self.client.post( reverse("source-create"), { "shelfmark": "test-shelfmark", # shelfmark is a required field - "holding_institution": hinst.id, # holding institution is a required field + "source_completeness": "1", # required field + "production_method": "1", # required field }, ) - self.assertEqual(response.status_code, 302) created_source = Source.objects.get(shelfmark="test-shelfmark") self.assertRedirects( @@ -106,13 +105,13 @@ def test_url_and_templates(self): def test_edit_source(self): source = make_fake_source() - hinst = make_fake_institution(siglum="FA-Ke") response = self.client.post( reverse("source-edit", args=[source.id]), { "shelfmark": "test-shelfmark", # shelfmark is a required field, - "holding_institution": hinst.id, # holding institution is a required field + "source_completeness": "1", # required field + "production_method": "1", # required field }, ) @@ -981,10 +980,14 @@ def test_ordering(self) -> None: Order is currently available by country, city + institution name (parameter: "city_institution"), and siglum + shelfmark. Siglum + shelfmark is the default. """ - # Create a bunch of sources sources = [] + # Add a source from a private collector + private_collector = make_fake_institution(is_private_collector=True) + sources.append(make_fake_source(holding_institution=private_collector)) + # Create a bunch of other sources for _ in range(10): - sources.append(make_fake_source()) + inst = make_fake_institution(siglum=faker.word()) + sources.append(make_fake_source(holding_institution=inst)) # Default ordering is by siglum and shelfmark, ascending with self.subTest("Default ordering"): response = self.client.get(reverse("source-list")) @@ -992,7 +995,13 @@ def test_ordering(self) -> None: expected_source_order = sorted( sources, key=lambda source: ( - source.holding_institution.siglum, + 0 if source.holding_institution else 1, + 1 if source.holding_institution.is_private_collector else 0, + ( + source.holding_institution.siglum + if source.holding_institution.siglum + else "" + ), source.shelfmark, ), )