Add task to delete unlinked Institution and Location objects#1406
Open
Add task to delete unlinked Institution and Location objects#1406
Conversation
Create institution/tasks.py with task_delete_unlinked_institutions_and_locations: - Step 1: Set institution=None on *History instances with RawOrganizationMixin data filled - Step 2: Delete Institution instances not linked to any *History (clear FK/M2M first) - Step 3: Delete all Location instances (clear FK/M2M first) Add comprehensive tests in institution/tests.py Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Create task to eliminate Institution and Location without links to other objects
Add task to delete unlinked Institution and Location objects
Mar 15, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a Celery maintenance task to unlink *History objects from legacy Institution records when RawOrganizationMixin fields are populated, then attempts to delete now-unlinked legacy Institution/Location records, with accompanying automated tests.
Changes:
- Introduces
task_delete_unlinked_institutions_and_locations(+ helper_build_raw_data_filter) to unlink histories and delete orphaned data. - Adds a comprehensive Django
TestCasesuite covering unlinking, deletion, FK/M2M cleanup, and return counts.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
institution/tasks.py |
New Celery task to unlink *History.institution, delete unlinked Institution, and delete Location records. |
institution/tests.py |
New unit tests validating task behavior and returned deletion counts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+103
to
+107
| # Step 3: Delete all Location instances | ||
| deleted_locations = Location.objects.count() | ||
| Location.objects.update(city=None, state=None, country=None) | ||
| Location.objects.all().delete() | ||
|
|
Comment on lines
+73
to
+97
| all_institution_ids = set( | ||
| Institution.objects.values_list("id", flat=True) | ||
| ) | ||
| linked_institution_ids = set() | ||
| for history_class in history_classes: | ||
| linked_institution_ids.update( | ||
| history_class.objects.filter( | ||
| institution__institution__isnull=False, | ||
| ).values_list("institution__institution_id", flat=True) | ||
| ) | ||
| unlinked_ids = all_institution_ids - linked_institution_ids | ||
|
|
||
| # Clear M2M fields for unlinked institutions | ||
| for inst in Institution.objects.filter(id__in=unlinked_ids): | ||
| inst.institution_type_scielo.clear() | ||
|
|
||
| # Clear FK fields and delete | ||
| Institution.objects.filter(id__in=unlinked_ids).update( | ||
| institution_identification=None, | ||
| location=None, | ||
| ) | ||
| deleted_institutions = Institution.objects.filter( | ||
| id__in=unlinked_ids | ||
| ).count() | ||
| Institution.objects.filter(id__in=unlinked_ids).delete() |
| for history_class in history_classes: | ||
| linked_institution_ids.update( | ||
| history_class.objects.filter( | ||
| institution__institution__isnull=False, |
Comment on lines
+85
to
+87
| # Clear M2M fields for unlinked institutions | ||
| for inst in Institution.objects.filter(id__in=unlinked_ids): | ||
| inst.institution_type_scielo.clear() |
| self.assertTrue(Country.objects.filter(pk=self.country.pk).exists()) | ||
| self.assertTrue(State.objects.filter(pk=self.state.pk).exists()) | ||
| self.assertTrue(City.objects.filter(pk=self.city.pk).exists()) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
O que esse PR faz?
Celery task
task_delete_unlinked_institutions_and_locationsque limpa objetosInstitutioneLocationórfãos após a migração para camposRawOrganizationMixin.Três etapas:
*History(OwnerHistory, PublisherHistory, SponsorHistory, CopyrightHolderHistory) com qualquer campoRawOrganizationMixinpreenchido, setainstitution = NoneInstitutionsem vínculo com nenhuma*History(via cadeiaHistory.institution → BaseInstitution → Institution), limpa FK/M2M e deletaLocatione deletaOnde a revisão poderia começar?
institution/tasks.py— arquivo único com a task e helper_build_raw_data_filter().Como este poderia ser testado manualmente?
Ou via Celery worker/beat com o nome
task_delete_unlinked_institutions_and_locations.Testes automatizados em
institution/tests.pycobrem: unlinking com raw data preenchido, preservação de vínculos sem raw data, deleção de Institution órfão, preservação de Institution vinculado, limpeza de FK/M2M antes da deleção, deleção de Location.Algum cenário de contexto que queira dar?
A task
task_replace_institution_by_raw_institutionjá popula os camposRawOrganizationMixina partir dos dados do AMJournal. Esta nova task é o passo seguinte: após a migração dos dados para campos raw, os objetosInstitutioneLocationlegados que não possuem mais vínculos podem ser eliminados.A cadeia de FK é indireta:
*History.institution→BaseInstitutionsubclass (Owner, Publisher, etc.) →Institution. O step 2 resolve isso consultandoinstitution__institution_idnas *History.Screenshots
N/A
Quais são tickets relevantes?
Referências
journal/tasks.py—task_replace_institution_by_raw_institution(task predecessora)core/models.py—RawOrganizationMixin(campos raw_text, raw_institution_name, etc.)institution/models.py—BaseInstitution,InstitutionOriginal prompt
📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.