diff --git a/django/meleager/fixtures/README.md b/django/meleager/fixtures/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7521eaefdee23f93c20b55add47f279bef96333f --- /dev/null +++ b/django/meleager/fixtures/README.md @@ -0,0 +1,7 @@ +## `test_data.json` + +* Work: no parameters +* Book: number 12 +* Passage + * fragment 42, no sub_fragment ('') + * fragment 12, sub_fragment abc \ No newline at end of file diff --git a/django/meleager/fixtures/test_data.json b/django/meleager/fixtures/test_data.json new file mode 100644 index 0000000000000000000000000000000000000000..43c751c1dc69b128ae4edde0dd53af8269f569c3 --- /dev/null +++ b/django/meleager/fixtures/test_data.json @@ -0,0 +1 @@ +[{"model": "meleager.work", "pk": 1, "fields": {"created_at": "2020-11-14T02:33:59.818Z", "updated_at": "2020-11-14T02:33:59.818Z", "creator": null, "last_editor": null, "urn": null, "descriptions": [], "alternative_urns": [], "names": []}}, {"model": "meleager.book", "fields": {"created_at": "2020-11-14T02:34:10.052Z", "updated_at": "2020-11-14T02:34:10.052Z", "creator": null, "last_editor": null, "work": 1, "number": 12, "descriptions": []}}, {"model": "meleager.passage", "fields": {"created_at": "2020-11-14T02:34:28.654Z", "updated_at": "2020-11-14T02:34:28.654Z", "creator": null, "last_editor": null, "urn": null, "validation": 0, "city": null, "book": [12, 1], "fragment": 42, "sub_fragment": "", "descriptions": [], "alternative_urns": [], "authors": [], "images": [], "comments": [], "external_references": [], "internal_references": [], "manuscripts": [], "keywords": []}}, {"model": "meleager.passage", "fields": {"created_at": "2020-11-14T02:34:49.041Z", "updated_at": "2020-11-14T02:34:49.041Z", "creator": null, "last_editor": null, "urn": null, "validation": 0, "city": null, "book": [12, 1], "fragment": 12, "sub_fragment": "abc", "descriptions": [], "alternative_urns": [], "authors": [], "images": [], "comments": [], "external_references": [], "internal_references": [], "manuscripts": [], "keywords": []}}] \ No newline at end of file diff --git a/django/meleager/models/book.py b/django/meleager/models/book.py index 7583c2978c03277e37f5aa4882a1e60dc2095342..b3927ab0eaf13630a6414662697b32ea8484e957 100644 --- a/django/meleager/models/book.py +++ b/django/meleager/models/book.py @@ -3,16 +3,27 @@ Mahuf. """ +from django.apps import apps from django.db import models from .mixins import DescriptableResourceMixin, EditableResourceMixin +class BookManager(models.Manager): + def get_by_natural_key(self, number, work_pk): + work = apps.get_model("meleager", "Work").objects.get(pk=work_pk) + return self.get(number=number, work=work) class Book(DescriptableResourceMixin, EditableResourceMixin, models.Model): """ Book model """ + objects = BookManager() + work = models.ForeignKey("meleager.Work", on_delete=models.CASCADE) number = models.IntegerField("Book number", null=False, db_index=True) + def natural_key(self): + return (self.number, self.work.pk) + natural_key.dependencies = ['meleager.Work'] + def __str__(self): return f"Book {self.number}" diff --git a/django/meleager/models/passage.py b/django/meleager/models/passage.py index d41dd1a315612808b731901a1dfbd164e0491fc5..2f2f71f572ed2f36af511ecdf52223c0c230c2e7 100644 --- a/django/meleager/models/passage.py +++ b/django/meleager/models/passage.py @@ -1,6 +1,7 @@ import re from urllib.parse import urlparse +from django.apps import apps from django.conf import settings from django.db import models from django.http import HttpResponseBadRequest @@ -14,6 +15,10 @@ from .mixins import ( ) from .urn import URN +class PassageManager(models.Manager): + def get_by_natural_key(self, fragment, sub_fragment, *book_natural_key): + book = apps.get_model("meleager", "Book").objects.get_by_natural_key(*book_natural_key) + return self.get(fragment=fragment, sub_fragment=sub_fragment, book=book) class Passage( EditableResourceMixin, @@ -24,6 +29,8 @@ class Passage( ): """ Passage model """ + objects = PassageManager() + authors = models.ManyToManyField("meleager.Author") city = models.ForeignKey( "meleager.City", @@ -81,5 +88,9 @@ class Passage( help_text="The keywords that tag this resource.", ) + def natural_key(self): + return (self.fragment, self.sub_fragment) + self.book.natural_key() + natural_key.dependencies = ['meleager.Work', 'meleager.Book'] + def __str__(self): return f"Passage {self.book.number}.{self.fragment}{self.sub_fragment}" diff --git a/django/meleager/models/work.py b/django/meleager/models/work.py index 2fc384a684f97c80e90709c296be358a34957455..be9b439a8d8b8fc3a02750f34abe4345fd9503fa 100644 --- a/django/meleager/models/work.py +++ b/django/meleager/models/work.py @@ -6,13 +6,13 @@ from .mixins import ( AlternativeURNResourceMixin, ) - class Work( EditableResourceMixin, DescriptableResourceMixin, AlternativeURNResourceMixin, models.Model, ): + names = models.ManyToManyField( "meleager.Name", related_name="mlgr_works", diff --git a/django/user/fixtures/test_admin.json b/django/user/fixtures/test_admin.json new file mode 100644 index 0000000000000000000000000000000000000000..97df4b486f2fa0b7d65208a55bff44dfc3fd8ae4 --- /dev/null +++ b/django/user/fixtures/test_admin.json @@ -0,0 +1 @@ +[{"model": "user.user", "pk": 1, "fields": {"password": "!xeTTOcyuHKdRJyOPkNaiXosuRkntzKOZKV26QBVo", "last_login": null, "is_superuser": false, "username": "AnonymousUser", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2020-11-14T02:31:42.180Z", "institution": "", "groups": [], "user_permissions": []}}, {"model": "user.user", "pk": 2, "fields": {"password": "pbkdf2_sha256$216000$1NDKDHZcziZa$sxZD899PegMg0IOiWOFso+F+gmSF5RXBPOkyrC6OvZ4=", "last_login": null, "is_superuser": true, "username": "test_admin", "first_name": "", "last_name": "", "email": "admin@admin.com", "is_staff": true, "is_active": true, "date_joined": "2020-11-14T02:32:13.175Z", "institution": "", "groups": [], "user_permissions": []}}] \ No newline at end of file diff --git a/django/user/models.py b/django/user/models.py index 16023ce7ead9ba197d9ba0e0ee75e2ac3804d553..b3cf202999f34ed3cd1e271ba2e49c50eaf1a2ae 100644 --- a/django/user/models.py +++ b/django/user/models.py @@ -4,3 +4,6 @@ from django.db import models class User(AbstractUser): institution = models.TextField(help_text="The institution this user belongs to.") + + def natural_key(self): + return (self.username,) diff --git a/django/web/tests/test_add_comment_passage.py b/django/web/tests/test_add_comment_passage.py index 3656f5b36728535dae253327372e0b5f56d5a05f..f84f0e8bc3f152c58c908805a8b0c8debdb69316 100644 --- a/django/web/tests/test_add_comment_passage.py +++ b/django/web/tests/test_add_comment_passage.py @@ -1,4 +1,5 @@ from django.test import TestCase +from django.urls import reverse from meleager.models import Work, Book, Passage, Description from meleager.models import Comment @@ -8,14 +9,15 @@ from web.forms.description import DescriptionForm class AddCommentFormPassage(TestCase): + fixtures = ['test_data.json'] + def setUp(self): - self.work = Work.objects.create() - self.book = Book.objects.create(work=self.work, number=12) - self.passage = Passage.objects.create(book=self.book, fragment=42) + book = Book.objects.first() + self.passage = Passage.objects.get(book=book, fragment=42) def test_form(self): response = self.client.post( - f"/comments/add/passage/{self.passage.pk}", + reverse("web:comment-add", args=(self.passage.pk,)), data={ "comment_title": "TEST COMMENT", "description": "TEST DESCRIPTION", diff --git a/django/web/tests/test_passage.py b/django/web/tests/test_passage.py new file mode 100644 index 0000000000000000000000000000000000000000..4a15bbcb40fbce9785a812d7e557da7838fd61b7 --- /dev/null +++ b/django/web/tests/test_passage.py @@ -0,0 +1,22 @@ +from django.test import TestCase + +from meleager.models import Book, Work +from web.models import APPassage, APScholium + + +class TestURNPassage(TestCase): + fixtures = ["test_data.json"] + + def test_homepage_ok(self): + resp = self.client.get("/") + self.assertEqual(resp.status_code, 200) + self.assertContains(resp, "12.42") + self.assertContains(resp, "12.12abc") + + def test_passage1_ok(self): + resp = self.client.get("/passages/urn:cts:greekLit:tlg7000.tlg001.ag:12.42") + self.assertEqual(resp.status_code, 200) + + def test_passage2_ok(self): + resp = self.client.get("/passages/urn:cts:greekLit:tlg7000.tlg001.ag:12.12abc") + self.assertEqual(resp.status_code, 200) diff --git a/django/web/tests/test_urn_reverse.py b/django/web/tests/test_urn_reverse.py deleted file mode 100644 index 8bbaeda8f1019a713733a2b319b721db407caf1c..0000000000000000000000000000000000000000 --- a/django/web/tests/test_urn_reverse.py +++ /dev/null @@ -1,30 +0,0 @@ -from django.test import TestCase - -from meleager.models import Book, Work -from web.models import APPassage, APScholium - - -class TestURNPassage(TestCase): - def setUp(self): - self.work = Work.objects.create() - self.book = Book.objects.create(work=self.work, number=12) - self.passage = APPassage.objects.create(book=self.book, fragment=42) - - def test_homepage_ok(self): - resp = self.client.get("/") - self.assertEqual(resp.status_code, 200) - self.assertContains(resp, "12.42") - - def test_passage_ok(self): - resp = self.client.get("/passages/urn:cts:greekLit:tlg7000.tlg001.ag:12.42") - self.assertEqual(resp.status_code, 200) - - def test_urn_value_passage(self): - self.assertEquals( - self.passage.urn_value, "urn:cts:greekLit:tlg7000.tlg001.ag:12.42" - ) - - self.passage.sub_fragment = "b" - self.assertEquals( - self.passage.urn_value, "urn:cts:greekLit:tlg7000.tlg001.ag:12.42b" - )