Skip to content

Conversation

@robertatakenaka
Copy link
Member

@robertatakenaka robertatakenaka commented Jan 20, 2026

Refatoração do modelo License e LicenseStatement

Descrição

Refatora a estrutura de licenças para armazenar informações de forma normalizada, substituindo o campo de texto article_license por uma FK para o modelo License com suporte a versionamento.

Mudanças principais

core/models.py

  • Adiciona campo version ao modelo License
  • Altera unique_together para (license_type, version)
  • Adiciona properties display_name, url e data em License
  • Refatora LicenseStatement para usar license como chave principal
  • Melhora método parse_url para extrair tipo, versão e idioma de URLs CC

article/models.py

  • Remove lógica de auto-população de article_license no método autocomplete
  • Adiciona property license_url para obter URL da licença

article/sources/xmlsps.py

  • Atualiza set_license para criar objetos License a partir do XML
  • Faz parse da URL da licença e cria registro normalizado

article/tasks.py

  • Atualiza task transfer_license_statements_fk_to_article_license para usar FK license
  • Cria License a partir dos dados de LicenseStatement quando necessário

API

  • Adiciona LicenseSerializer com campos url, license_type e version
  • Atualiza ArticleSerializer com campo license (objeto) e license_statements

Admin

  • Adiciona LicenseViewSet como snippet no Wagtail admin

Migration

  • core/migrations/0009_alter_licensestatement_options_and_more.py

Checklist

  • Executar migration em ambiente de teste
  • Executar task de migração de dados transfer_license_statements_fk_to_article_license
  • Validar API /api/v1/article/

…ement

- Add version field to License model
- Change unique_together to (license_type, version)
- Add display_name, url and data properties to License
- Update License.get/create/create_or_update to support version
- Refactor LicenseStatement to use license as primary key
- Improve parse_url method with better URL parsing
- Add data property to LicenseStatement
- Update __str__ methods for better display
- Add new LicenseSerializer with url, license_type and version fields
- Import License model
- Register License as snippet viewset
- Add list display, filters and search fields
- Enable inspect view
- Fix import to use LICENSE_TYPES from core.choices instead of choices module
…perty

- Remove auto-population of article_license in autocomplete method
- Add license_url property to get URL from license or license_statements
- Import LicenseStatement and License from core.models
- Add user parameter to set_license function
- Parse license URL and create License object instead of storing URL string
- Update load_article to pass user to set_license
- Import License model
- Change filter from article_license__isnull to license__isnull
- Update logic to use license FK from license_statements
- Create License from statement data if needed
- Update bulk_update fields
…lizer

- Import LicenseSerializer from core.api
- Change license field to use LicenseSerializer (many=False)
- Add license_statements field with LicenseStatementSerializer
- Add license_statements to fields list
Copilot AI review requested due to automatic review settings January 20, 2026 18:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds license URL generation functionality to the Article model by enhancing the License model with a version field and implementing URL property for Creative Commons licenses. The PR refactors license-related models and updates article processing workflows to use the new license structure.

Changes:

  • Added version field to License model and updated unique constraints to (license_type, version)
  • Implemented url property on License model to generate Creative Commons license URLs
  • Refactored LicenseStatement model methods to use License foreign key as primary identifier
  • Updated article XML parsing and data migration tasks to use new License model structure

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
core/models.py Added version field to License, implemented url property, refactored LicenseStatement methods, and improved parse_url implementation
core/migrations/0009_alter_licensestatement_options_and_more.py Database migration to add version field, update unique constraints, and add indexes
core/api/v1/serializers.py Added LicenseSerializer with url, license_type, and version fields
core/wagtail_hooks.py Registered LicenseViewSet for admin interface management
journal/models.py Updated imports to include LICENSE_TYPES from core.choices
article/models.py Added license_url property and removed deprecated article_license logic from complete_data
article/api/v1/serializers.py Updated ArticleSerializer to include separate license and license_statements fields
article/tasks.py Refactored transfer_license_statements_fk_to_article_license to work with new License model
article/sources/xmlsps.py Updated set_license to parse URLs and create License objects with version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

except cls.DoesNotExist:
return cls.create(user, license_type)
return cls.create(user, license_type, version)

Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

There is trailing whitespace at the end of this line. This should be removed to maintain code cleanliness.

Suggested change

Copilot uses AI. Check for mistakes.
if not instance.license and first.data:
data = first.data
instance.license = License.create_or_update(user, license_type=data.get("license_type"), version=data.get("license_version"))

Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

There is trailing whitespace at the end of this line. This should be removed to maintain code cleanliness.

Suggested change

Copilot uses AI. Check for mistakes.
),
models.Index(fields=["url"]),
models.Index(fields=["license", "language"]),
]
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The LicenseStatement model no longer has a unique_together constraint after the migration removes it. This means duplicate entries with the same license and language combination can now be created. However, the 'get' method at line 486 still expects to retrieve a single object and handles MultipleObjectsReturned. Consider whether this is the intended behavior or if a unique constraint should be maintained on (license, language) to prevent duplicate entries.

Suggested change
]
]
unique_together = (("license", "language"),)

Copilot uses AI. Check for mistakes.
"""
Parse Creative Commons license URL.
Exemplos de URLs:
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The word "Exemplos" is in Portuguese. For consistency with the rest of the codebase, consider using English ("Examples") in the documentation.

Suggested change
Exemplos de URLs:
Examples of URLs:

Copilot uses AI. Check for mistakes.
return cls.create(user, license_type, version)

@property
def url(self):
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

If license_type is None or empty, this property will generate a malformed URL like "https://creativecommons.org/licenses/None/4.0/". Consider adding a check to return None when license_type is not set, or validating that license_type is not None before generating the URL.

Suggested change
def url(self):
def url(self):
if not self.license_type:
return None

Copilot uses AI. Check for mistakes.

class Meta:
unique_together = [("license_type",)]
unique_together = [("license_type", "version")]
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The unique_together constraint on (license_type, version) allows both fields to be NULL. In databases, NULL values are treated specially in unique constraints - multiple records with (NULL, NULL) are typically allowed. This means multiple License objects with both fields as NULL can be created. If this is not the intended behavior, consider adding validation to ensure at least license_type is provided, or use a different uniqueness constraint approach.

Copilot uses AI. Check for mistakes.
Comment on lines +1012 to +1018
except (AttributeError, TypeError):
pass
try:
url = self.license_statements.first().url
if url:
return url
except (AttributeError, TypeError):
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

'except' clause does nothing but pass and there is no explanatory comment.

Suggested change
except (AttributeError, TypeError):
pass
try:
url = self.license_statements.first().url
if url:
return url
except (AttributeError, TypeError):
except (AttributeError, TypeError):
# Missing or malformed primary license; fall back to license statements.
pass
try:
url = self.license_statements.first().url
if url:
return url
except (AttributeError, TypeError):
# No license statements or invalid URL; treat as no license URL available.

Copilot uses AI. Check for mistakes.
@robertatakenaka robertatakenaka merged commit c657706 into scieloorg:main Jan 23, 2026
9 of 11 checks passed
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.

1 participant