Skip to content

Commit

Permalink
Add support for UniqueConstraint for uniqueness validation
Browse files Browse the repository at this point in the history
  • Loading branch information
laymonage authored and gasman committed Dec 18, 2024
1 parent c6ff485 commit 4026116
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 2 deletions.
4 changes: 3 additions & 1 deletion modelcluster/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ def validate_unique(self):
forms_to_delete = self.deleted_forms
valid_forms = [form for form in self.forms if form.is_valid() and form not in forms_to_delete]
for form in valid_forms:
unique_checks, date_checks = form.instance._get_unique_checks()
unique_checks, date_checks = form.instance._get_unique_checks(
include_meta_constraints=True
)
all_unique_checks.update(unique_checks)
all_date_checks.update(date_checks)

Expand Down
27 changes: 27 additions & 0 deletions tests/migrations/0013_add_log_category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.2.16 on 2024-11-25 12:55

from django.db import migrations, models
import django.db.models.deletion
import modelcluster.fields


class Migration(migrations.Migration):

dependencies = [
('tests', '0012_add_record_label'),
]

operations = [
migrations.CreateModel(
name='LogCategory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32)),
('log', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='categories', to='tests.log')),
],
),
migrations.AddConstraint(
model_name='logcategory',
constraint=models.UniqueConstraint(fields=('log', 'name'), name='unique_log_category'),
),
]
16 changes: 16 additions & 0 deletions tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,22 @@ def __str__(self):
return "[%s] %s" % (self.time.isoformat(), self.data)


class LogCategory(models.Model):
log = ParentalKey(Log, related_name="categories", on_delete=models.CASCADE)
name = models.CharField(max_length=32)

def __str__(self):
return self.name

class Meta:
constraints = [
models.UniqueConstraint(
fields=["log", "name"],
name="unique_log_category",
)
]


class Document(ClusterableModel):
title = models.CharField(max_length=255)
file = models.FileField(upload_to='documents')
Expand Down
24 changes: 23 additions & 1 deletion tests/tests/test_cluster_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django import VERSION as DJANGO_VERSION
from django.core.exceptions import ValidationError
from django.test import TestCase
from tests.models import Band, BandMember, Album, Restaurant, Article, Author, Document, Gallery, Song
from tests.models import Band, BandMember, Album, Log, Restaurant, Article, Author, Document, Gallery, Song
from modelcluster.forms import ClusterForm
from django.forms import Textarea, CharField
from django.forms.widgets import TextInput, FileInput
Expand Down Expand Up @@ -770,6 +770,28 @@ class Meta:
})
self.assertFalse(form.is_valid())

def test_unique_constraint(self):
class LogForm(ClusterForm):
class Meta:
model = Log
fields = ["data"]
formsets = ["categories"]

form = LogForm({
"data": "User signed in",

"categories-TOTAL_FORMS": 2,
"categories-INITIAL_FORMS": 0,
"categories-MAX_NUM_FORMS": 1000,

"categories-0-name": "user",
"categories-0-id": "",

"categories-1-name": "user",
"categories-1-id": "",
})
self.assertFalse(form.is_valid())


class FormWithM2MTest(TestCase):
def setUp(self):
Expand Down

0 comments on commit 4026116

Please sign in to comment.