diff --git a/backend/src/backend/models.py b/backend/src/backend/models.py index 5908cd0..1ee4492 100644 --- a/backend/src/backend/models.py +++ b/backend/src/backend/models.py @@ -8,7 +8,7 @@ import pydantic import sqlalchemy -from backend.constants import BackendConf +from backend.constants import BackendConf, logger METADATA_MAX_LEN = 2048 KIND_TEXT: str = "text" @@ -75,6 +75,20 @@ class Meta(BaseMeta): def __repr__(self): return f"Language(code={self.code}, name={self.name})" + async def get_create_or_update(code: str, name: str, native: str): + language, created = await Language.objects.get_or_create( + code=code, _defaults={"name": name, "native": native} + ) + if created is False and (language.name != name or language.native != native): + logger.warning( + f"Updating language values for {language.code} from {language.name}/" + f"{language.native} to {name}/{native}" + ) + language.name = name + language.native = native + await language.update() + return language + class TagMixin: """ZIM Tag is a text slug stored along others in `Tags` metadata diff --git a/backend/src/backend/routes/books.py b/backend/src/backend/routes/books.py index c0e7579..e2ffb68 100644 --- a/backend/src/backend/routes/books.py +++ b/backend/src/backend/routes/books.py @@ -126,7 +126,7 @@ async def create_book(book_payload: BookAddSchema): for lang_code in book_payload.metadata["Language"].split(","): native_name, english_name = find_language_names(lang_code) - language, _ = await Language.objects.get_or_create( + language = await Language.get_create_or_update( code=lang_code, name=english_name, native=native_name ) await book.languages.add(language) diff --git a/backend/src/demo/data.py b/backend/src/demo/data.py index fdef0b9..1aab1ca 100644 --- a/backend/src/demo/data.py +++ b/backend/src/demo/data.py @@ -153,7 +153,7 @@ async def load_fixture(): iso_639_3_lang_code = get_language_details(lang_code)["iso-639-3"] - language, _ = await Language.objects.get_or_create( + language = await Language.get_create_or_update( code=iso_639_3_lang_code, name=english_name, native=native_name ) await book.languages.add(language) diff --git a/backend/tests/test_books_endpoint.py b/backend/tests/test_books_endpoint.py index 5bb2916..8f73d19 100644 --- a/backend/tests/test_books_endpoint.py +++ b/backend/tests/test_books_endpoint.py @@ -13,6 +13,7 @@ KIND_TEXT, Book, BookMetadata, + Language, Title, TitleMetadata, ) @@ -20,7 +21,7 @@ @pytest.mark.asyncio -async def test_add_book(client, book_dict, clear_book_dict): +async def test_add_book_create_language(client, book_dict, clear_book_dict): response = await client.post("/v1/books/add", json=book_dict) assert response.status_code == 201 assert response.headers.get("Content-Type") == "application/json" @@ -38,6 +39,21 @@ async def test_add_book(client, book_dict, clear_book_dict): assert book.zimcheck == book_dict["zimcheck"] +@pytest.mark.asyncio +async def test_add_book_update_language( + client, book_dict, clear_book_dict, language_eng +): + # language_eng is already created in DB but its name and native properties are wrong + # since they have been updated in Babel + response = await client.post("/v1/books/add", json=book_dict) + assert response.status_code == 201 + assert response.headers.get("Content-Type") == "application/json" + + language = await Language.objects.get(code="eng") + assert language.native == "English (United States)" + assert language.name == "English (United States)" + + @pytest.mark.asyncio async def test_of_rollback(client, book_dict): ident = get_ident_from_name(book_dict["metadata"]["Name"])