Skip to content

Replace deprecated unique_together with UniqueConstraint#262

Open
goodtune wants to merge 2 commits intomainfrom
claude/migrate-unique-constraints-Pz7ku
Open

Replace deprecated unique_together with UniqueConstraint#262
goodtune wants to merge 2 commits intomainfrom
claude/migrate-unique-constraints-Pz7ku

Conversation

@goodtune
Copy link
Owner

@goodtune goodtune commented Feb 1, 2026

Summary

Migrate all model Meta classes from the deprecated unique_together option to the modern UniqueConstraint API across the news and competition applications.

Changes

  • touchtechnology/news/models.py: Converted ArticleTranslation model's unique_together constraint to UniqueConstraint
  • tournamentcontrol/competition/models.py: Converted unique_together to UniqueConstraint for 11 models:
    • Season (2 constraints)
    • Division (2 constraints)
    • Stage (2 constraints)
    • StageGroup (1 constraint)
    • Team (1 constraint)
    • ClubAssociation (1 constraint)
    • TeamAssociation (1 constraint)
    • SeasonReferee (1 constraint)
    • SeasonAssociation (1 constraint)
    • LadderSummary (1 constraint)
    • SeasonExclusionDate (1 constraint)
    • DivisionExclusionDate (1 constraint)

Implementation Details

  • Added UniqueConstraint import to both modified files
  • Each constraint now includes an explicit name parameter following Django naming conventions (e.g., "news_translation_unique_article_locale")
  • Updated the Team.clean() method comment to reflect the new constraint approach
  • All constraints maintain the same field combinations and uniqueness guarantees as the original unique_together definitions
  • This change aligns with Django's deprecation of unique_together in favor of the more flexible constraints API

https://claude.ai/code/session_01FHqKHFMm1n5oLmaXxrNefQ

Replace deprecated `unique_together` Meta option with the more modern
`UniqueConstraint` in the `constraints` option across all models:

Competition app:
- Season: title+competition, slug+competition
- Division: title+season, slug+season
- Stage: title+division, slug+division
- StageGroup: stage+order
- Team: title+division
- ClubAssociation: club+person
- TeamAssociation: team+person
- SeasonReferee: season+person
- SeasonAssociation: season+person
- LadderSummary: stage+team
- SeasonExclusionDate: season+date
- DivisionExclusionDate: division+date

News app:
- Translation: article+locale

Note: The `django-modelforms` package's `UniqueTogetherMixin` only
checks `opts.unique_together`. It should be updated to also check
`opts.constraints` for `UniqueConstraint` entries to maintain proper
form validation when fields are excluded from forms.

https://claude.ai/code/session_01FHqKHFMm1n5oLmaXxrNefQ
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 migrates Django model constraints from the deprecated unique_together Meta option to the modern UniqueConstraint API. The changes affect 13 models across two applications (news and competition), replacing tuple-based unique constraints with explicit named constraint objects.

Changes:

  • Added UniqueConstraint imports to both modified files
  • Converted 1 model in the news application (ArticleTranslation)
  • Converted 12 models in the competition application with a total of 15 unique constraints
  • Updated a code comment in Team.clean() method to reflect the new constraint approach

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
touchtechnology/news/models.py Added UniqueConstraint import and converted ArticleTranslation model's unique_together to UniqueConstraint with explicit naming
tournamentcontrol/competition/models.py Added UniqueConstraint import and converted 12 models (Season, Division, Stage, StageGroup, Team, ClubAssociation, TeamAssociation, SeasonReferee, SeasonAssociation, LadderSummary, SeasonExclusionDate, DivisionExclusionDate) from unique_together to UniqueConstraint with consistent naming pattern; updated Team.clean() comment

Comment on lines +515 to +524
constraints = [
UniqueConstraint(
fields=["title", "competition"],
name="competition_season_unique_title_competition",
),
UniqueConstraint(
fields=["slug", "competition"],
name="competition_season_unique_slug_competition",
),
]
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

This PR modifies model Meta classes from unique_together to UniqueConstraint, which requires database migrations to update the constraint definitions in the database schema. However, no migration files have been created for these changes.

You need to generate and include the migrations by running:

python manage.py makemigrations

This will create migration files that:

  1. Remove the old unnamed unique constraints created by unique_together
  2. Add the new named UniqueConstraint objects

Without these migrations, the database schema will be inconsistent with the model definitions, which could lead to:

  • Migration conflicts in production
  • Schema detection failures
  • Inability for other developers to apply these changes to their databases

Copilot uses AI. Check for mistakes.
Comment on lines +139 to +144
constraints = [
UniqueConstraint(
fields=["article", "locale"],
name="news_translation_unique_article_locale",
),
]
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

This PR modifies the model Meta class from unique_together to UniqueConstraint, which requires a database migration. However, no migration file has been created for this change.

You need to generate and include the migration by running:

python manage.py makemigrations news

Without this migration, the database schema will be inconsistent with the model definition.

Copilot uses AI. Check for mistakes.
Comment on lines +2584 to +2589
constraints = [
UniqueConstraint(
fields=["division", "date"],
name="competition_divisionexclusiondate_unique_division_date",
),
]
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

The PR description states "Converted unique_together to UniqueConstraint for 11 models" but actually 12 models were converted in the competition application. The list includes all 11 models mentioned plus DivisionExclusionDate which was not counted. Consider updating the PR description for accuracy.

Copilot uses AI. Check for mistakes.
@goodtune
Copy link
Owner Author

goodtune commented Feb 6, 2026

@copilot bump the minimum version of django-modelforms to 1.0.

Copy link
Contributor

Copilot AI commented Feb 6, 2026

@goodtune I've opened a new pull request, #263, to work on those changes. Once the pull request is ready, I'll request review from you.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: goodtune <286798+goodtune@users.noreply.github.com>
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.

4 participants