Skip to content

Errata backend#5249

Open
gamboz wants to merge 5 commits into
openlibhums:masterfrom
sissamedialab:discussion-5238__errata-backend
Open

Errata backend#5249
gamboz wants to merge 5 commits into
openlibhums:masterfrom
sissamedialab:discussion-5238__errata-backend

Conversation

@gamboz
Copy link
Copy Markdown
Collaborator

@gamboz gamboz commented Mar 30, 2026

Add the possibility of linking an erratum to an article and register this relation with Crossref.

See also discussion 5238

  • add Genealogy model to link Articles
  • add crossmark/updates section to crossref xml deposit for errata

ATM, errata are so rare that no front-end or manager interface is changed here, but an "admin" is provided.

Please note the new dependency.

@gamboz gamboz force-pushed the discussion-5238__errata-backend branch 2 times, most recently from a91fe97 to 21289b6 Compare March 30, 2026 15:15
@gamboz gamboz marked this pull request as draft April 17, 2026 07:17
@gamboz
Copy link
Copy Markdown
Collaborator Author

gamboz commented Apr 17, 2026

@mauromsl we have been notified of a small incoherence in the XML deposit specs (see https://github.com/orgs/openlibhums/discussions/5238#discussioncomment-16599730 ).

I've moved this MR to "draft".

I'll complete it after we publish our first erratum and ping again.

@gamboz gamboz force-pushed the discussion-5238__errata-backend branch from 21289b6 to ab30aa4 Compare April 27, 2026 11:32
@gamboz gamboz force-pushed the discussion-5238__errata-backend branch 3 times, most recently from 1047bef to 9c75895 Compare April 27, 2026 13:04
gamboz added 3 commits April 27, 2026 15:06
from crossref support staff:

> [...]
> You can't totally omit the <crossmark_policy> element. For historical reasons, it's strictly required by the schema. But, as a workaround, you can just repeat the DOI of the original paper in that field. It's not used for anything, but it has to have a valid DOI in it.
@gamboz gamboz force-pushed the discussion-5238__errata-backend branch from 9c75895 to 796c658 Compare April 27, 2026 13:11
@@ -54,6 +54,31 @@
<item_number item_number_type="article_number">{{ article.object.pk }}</item_number>
</publisher_item>

{% if article.erratum_of %}
<crossmark>
<crossmark_policy>{{ article.object.journal|setting:'crossref_prefix' }}/not-used</crossmark_policy>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ according to XML specs, when recording an <update>, then a <crossmark_policy> DOI should also be provided, but, according to crossref support, that element is not used and any DOI would do. They suggested to use the article DOI, but I'm hardcoding a 10.11111/no-used fake DOI (I feel it's less confusing...)

@gamboz
Copy link
Copy Markdown
Collaborator Author

gamboz commented Apr 27, 2026

@mauromsl we talked with @ajrbyers on Friday and after a couple of minor fixes I'm setting this as ready for review.

Note that there might be some issues with migrations that (I think) are not related to these changes.
Please let me know if you want me to point this to some other branch.

@gamboz gamboz marked this pull request as ready for review April 27, 2026 13:23
@mauromsl mauromsl self-requested a review April 28, 2026 11:27
Copy link
Copy Markdown
Member

@mauromsl mauromsl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @gamboz great work. I've proposed two main changes inline:

  • Avoid using the section names as the mechanism for serializing the relationship type of "errata"
  • Use a linker table with a through model relationship, ideally repurposing the model that already lives in the hydra plugin.

Comment thread src/submission/models.py
Comment on lines +2641 to +2644
if self.section.name != "Erratum":
return None
if not self.ancestors.exists():
return None
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it makes sense on the context of this PR, section.name is a customizable (and translatable) entry. Since we are adding a new model to register the relationships between articles, it would make sense to codify this (and other relationships) as part of that model, rather than relying on the indirection of the section name.

Comment thread src/submission/models.py
Comment on lines +3424 to +3445
class Genealogy(models.Model):
"""
Maintain relations of type parent/children between articles.

This can be used, for instance, to link erratum to the original paper.
"""

parent = models.OneToOneField(
Article,
verbose_name=_("Original or main paper"),
on_delete=models.CASCADE,
related_name="genealogy",
)
children = SortedManyToManyField(
Article,
related_name="ancestors",
)

def __str__(self):
return f"Genealogy: {self.parent} has {self.children.count()} kids"


Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the community are asking for a few more relationship types such as addendum, correction and so on. We also have a model on the hydra plugin for registering relationships such as translations.

Would it work for your use case if we were to port the LinkedArticle model from Hydra plugin instead?

It behaves as a linking table, so there is one less join required when querying both sides of the relationship.

Comment thread requirements.txt
@@ -59,6 +59,7 @@ python-magic==0.4.27
pytz==2024.1
requests==2.32.4
six==1.16.0
django-sortedm2m~=3.1
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we go with the approach I proposed about registering a model that behaves as a linking table, we could also use our M2MOrderedThroughField. It would avoid the additional dependency and also maintain consistency with other ordered many to many relationships in the codebase.

@mauromsl mauromsl assigned gamboz and unassigned mauromsl Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants