# Dynamically populate constraints in Field.contribute\_to\_class

**URL:** <https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934>\
**Category:** ORM\
**Created:** [August 9, 2023, 10:28pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934 "2023-08-09T22:28:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![olivierdalang](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/olivierdalang/32/13579_2.png) [@olivierdalang](https://forum.djangoproject.com/u/olivierdalang)\
**Post date:** [August 9, 2023, 10:28pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/1 "2023-08-09T22:28:52Z")

</div>

Hey !

I’m writing a custom model field and would like it to come with a database CHECK constraint. The actual use case is DB validation of Django’s `choices`, to avoid invalid values (since the data can be edited from outside of Django).

I thought that could be done with `contribute_to_class`, and indeed it’s almost possible.

Here’s what I got so far:

```python
class ChoiceField(models.CharField):
    def contribute_to_class(self, cls, name, private_only=False):
        super().contribute_to_class(cls, name, private_only)
        accepted_values = [c[0] for c in self.choices]
        cls._meta.constraints.append(
            models.CheckConstraint(
                check=models.Q(**{f"{name}__in": accepted_values}),
                name=f"%(app_label)s_%(class)s_{name}_valid_choices"
            )
        )

```

It works exactly as I’d like when I specify an empty constraints list in my model’s Meta (meaning makemigrations will create the constraints).

But for some reason, if I don’t specify an empty list, or if my model has no Meta at all, the constraints aren’t picked up (makemigrations doesn’t create the constraints).

I stumbled about [this ticket](https://code.djangoproject.com/ticket/2888), which seems very similar, and where it was suggested to ask here (in that case, it was about “indexes”, and strangely they seem to have the exact opposite issue, where it works as expected without Meta, but the index is added twice with the Meta).

Does anyone understand what could be the cause of the issue ?  
Wouldn’t it be nice for Django to support this ? DB data validation is really a must when you can’t rely on python validation (migrating large amount of data, DB operated by other clients, etc…)

Cheers !!

Olivier

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 9, 2023, 10:36pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/2 "2023-08-09T22:36:24Z")

</div>

The easiest way to create those types of constraints is to define those choices in a “code table” and use a foreign key to relate the base table to it. (That’s what we do to enforce the integrity of those types of selections.)

---

<div class="post-metadata">

**Author:** ![olivierdalang](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/olivierdalang/32/13579_2.png) [@olivierdalang](https://forum.djangoproject.com/u/olivierdalang)\
**Post date:** [August 10, 2023, 8:03am UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/3 "2023-08-10T08:03:07Z")

</div>

Thanks for the suggestion ! Indeed that’s an approach, but that forces to store the values in the DB (and hence somehow sync them with the code), and also doesn’t work for more complex use cases (such as multiselect, where you’d store the selection as a postgres array of strings).

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 10, 2023, 12:20pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/4 "2023-08-10T12:20:19Z")

</div>

> [@olivierdalang](#):
>
> (and hence somehow sync them with the code),

No, there’s no “code” to be synced, because the data exists in the database. It eliminates the need for the code.

> [@olivierdalang](#):
>
> also doesn’t work for more complex use cases (such as multiselect, where you’d store the selection as a postgres array of strings).

Yes it does - it works quite fine. From a relational database perspective, the “multiselect” would be represented by a many-to-many relationship.

This is an exceedingly common technique used across numerous domains and frameworks. In fact, architecturally, I’ll maintain that it’s far superior to the code based method - precisely for the reasons you identify, among others.

It’s the _only_ way that we allow choice options to be defined.

---

<div class="post-metadata">

**Author:** ![carltongibson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/carltongibson/32/267_2.png) [@carltongibson](https://forum.djangoproject.com/u/carltongibson)\
**Post date:** [August 10, 2023, 5:37pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/5 "2023-08-10T17:37:01Z")

</div>

I’d quite like this to work. To generate check constraints from choices would be great.

> [@olivierdalang](#):
>
> It works exactly as I’d like when I specify an empty constraints list in my model’s Meta (meaning makemigrations will create the constraints).
> 
> But for some reason, if I don’t specify an empty list, or if my model has no Meta at all, the constraints aren’t picked up (makemigrations doesn’t create the constraints).

I’d be inclined to reduce that to a test case. Much easier to get people to comment against running code.

Q: does it work generating migrations when you **change** the choices? (Showing that in a test too would be handy.)

---

<div class="post-metadata">

**Author:** ![Lily-Foote](https://avatars.discourse-cdn.com/v4/letter/l/c37758/32.png) [@Lily-Foote](https://forum.djangoproject.com/u/Lily-Foote)\
**Post date:** [August 10, 2023, 9:27pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/6 "2023-08-10T21:27:39Z")

</div>

I’m definitely 👍 to having a clear, clean api for defining custom fields that set constraints. I agree with @carltongibson that we should add some tests to Django to prove it works and protect against regressions. I also think it’s worth documenting the pattern if it works reliably.

---

<div class="post-metadata">

**Author:** ![panicofr](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/panicofr/32/11850_2.png) [@panicofr](https://forum.djangoproject.com/u/panicofr)\
**Post date:** [August 12, 2023, 7:06am UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/7 "2023-08-12T07:06:49Z")

</div>

we use a subclass of `TextChoices` as an helper to define Constraints, but indeed a native API should be more cleaner and error-proof.

So definitely 👍 for me

However, I propose to implement the `ChoiceField` as a separate class accepting the real field as a parameter (like postgres `ArrayField` for example). In this way we could have char choices, int choices, etc…

---

<div class="post-metadata">

**Author:** ![olivierdalang](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/olivierdalang/32/13579_2.png) [@olivierdalang](https://forum.djangoproject.com/u/olivierdalang)\
**Post date:** [August 13, 2023, 2:24pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/8 "2023-08-13T14:24:24Z")

</div>

Ok I have this written as a test case (for now just an arbitrary constraint not involving choices, I think we need that to work reliably first before applying it to the ChoiceField use case) :

> <https://github.com/django/django/pull/17160>
>
> For now this is only a failing test case to run against official CI. Hope it's O…K to open such a PR. At some point this will hopefully become a PR to support having fields populating DB constraints in contribute\_to\_fields.
> 
> See https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934 for full context.

- sqlite / with Meta: works as expected
- sqlite / without Meta: the constraint work, but not picked up by makemigrations
- postgres / with Meta: fails with `DuplicateObject: constraint "test_constraint_model" for relation "modelwithmeta_model" already exists`
- postgres / without Meta: the constraint work, but not picked up by makemigrations

I’m not 100% sure what’s happening, in particular how it can be that the constraint work if not picked by makemigrations. How can they even be created in the database without a migration ?!

I think there’s nothing fishy going on with the test themselves (e.g. cross-test interference) since I get consistent results when running each test individually, and the issue resembles the similar ticket I was mentionning (btw it was [28888](https://code.djangoproject.com/ticket/28888) not 2888).

Any pointer at what could be at play ?

Once this simple case is sorted, I can add tests for more advanced scenarios too (inherited models, abstract models, etc).

---

<div class="post-metadata">

**Author:** ![nessita](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/nessita/32/12194_2.png) [@nessita](https://forum.djangoproject.com/u/nessita)\
**Post date:** [August 15, 2023, 12:20pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/9 "2023-08-15T12:20:34Z")

</div>

> [@KenWhitesell](#):
>
> > [@olivierdalang](#):
> >
> > also doesn’t work for more complex use cases (such as multiselect, where you’d store the selection as a postgres array of strings).
> 
> Yes it does - it works quite fine. From a relational database perspective, the “multiselect” would be represented by a many-to-many relationship.

I know the goal of this forum post is to make the general case works, but I figured I’d mention that [django-taggit](https://github.com/jazzband/django-taggit) solves this use case perfectly.

---

<div class="post-metadata">

**Author:** ![nessita](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/nessita/32/12194_2.png) [@nessita](https://forum.djangoproject.com/u/nessita)\
**Post date:** [August 16, 2023, 1:48am UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/10 "2023-08-16T01:48:55Z")

</div>

I’ve been doing some R&D to understand the original issue presented in this post. I think there are two main things to discuss, perhaps separately:

1. Why/how the constraints added by a field to its model’s constraint list (via `contribute_to_class`) is not picked up in the generated migration but it’s present in the DB (the original forum post).

2. A new feature that we could summarize using @Lily-Foote’s words as _[Let’s define] a clear, clean api for defining custom fields that set constraints._

Regarding item 1, the core of the issue is that `makemigrations` would not pick up the field-defined constraint but `migrate` will apply it. Specifically, for a simple model like (taken from the linked repo):

```python
from django.db import models

class ConstraintField(models.CharField):
    def contribute_to_class(self, cls, name, private_only=False):
        super().contribute_to_class(cls, name, private_only)
        cls._meta.constraints.append(
            models.CheckConstraint(
                check=models.Q(**{f"{name}__lte": 10}),
                name=f"test_constraint_{cls. __name__.lower()}_lte_value",
            )
        )

class DynamicModelWithConstraintField(models.Model):

    constrained_field = ConstraintField(max_length=10)

```

The generated migration is:

```python
    operations = [
        migrations.CreateModel(
            name='DynamicModelWithConstraintField',
            fields=[
                ('id', models.BigAutoField(...)), # reduced for brevity
                ('constrained_field', ticket_dynamic_constraints.models.ConstraintField(max_length=10)),
            ],
        ),
    ]

```

But `sqlmigrate` shows:

```sql
BEGIN;
--
-- Create model DynamicModelWithConstraintField
--
CREATE TABLE "ticket_dynamic_constraints_dynamicmodelwithconstraintfield" ("id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "constrained_field" varchar(10) NOT NULL, CONSTRAINT "test_constraint_dynamicmodelwithconstraintfield_lte_value" CHECK ("constrained_field" <= '10'));
COMMIT;

```

So clearly the constraint is (to be) added to the DB, but the migration machinery is not aware of it so further changes to the constraint result in all kinds of errors on future operations over those constraints.  
I realized that the code in the migrations’ state module, when calling `ModelState.from_model`, the `model._meta.original_attrs` is used to build the `ModelState` instance that represents the model, but this `original_attrs` is populated in `Options.contribute_to_class` and that’s not accounting/including what the Field has added to the model’s constraints (more debugging on this is needed, but for starter, there is a [if self.meta](https://github.com/django/django/blob/main/django/db/models/options.py#L191C9-L191C22) that does not do any magic if Meta is not defined.

So for this item, the main question is do we consider this a bug? From #28888 likely not since there is no documented support for adding indexes (or constraints) in `Field.contribute_to_class`, but it’s worth asking the question.

What about item 2? We could discuss whether a `get_constraints` would make sense as a new public method in the `Field` class. This could be a way to provide an API to solve the use case but I’m not sure if there is a similar precedent that would guide this decision making.

---

<div class="post-metadata">

**Author:** ![olivierdalang](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/olivierdalang/32/13579_2.png) [@olivierdalang](https://forum.djangoproject.com/u/olivierdalang)\
**Post date:** [August 16, 2023, 8:25pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/11 "2023-08-16T20:25:21Z")

</div>

Thanks @nessita for looking into this !!

I’ve pushed a [new commit](https://github.com/django/django/pull/17160/commits/a859c1f406669b718517f79830ac786c51877ebc#diff-7742b18b61cc293c98406ab1847265ccfe5e8fd41fd141e3ed177921dc588cdcR62) demonstrating the actual use case of the “ChoiceField”. It shows that when choices change, the constraints are dropped and recreated in the migrations (due to 1/ this test only passes in sqlite and requires `Meta.constraints = []` to be defined). So it seems we are really almost there already.

With that in mind, I would argue that `contribute_to_class` is actually a good candidate for 2/, and to treat 1/ as a bug ? Otherwise we’d very soon need `get_indexes` (the use case of #28888), and then maybe others as well. But of course that’s just my 2 cents, I don’t know much about Django’s internals and would be very happy with a `get_constraints`.

---

<div class="post-metadata">

**Author:** ![rsyring](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/rsyring/32/18554_2.png) [@rsyring](https://forum.djangoproject.com/u/rsyring)\
**Post date:** [January 19, 2024, 6:42pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/12 "2024-01-19T18:42:34Z")

</div>

FWIW, I’ve been using Python for over a decade but mostly Flask/SQLAlchemy based projects. I recently started working with Django and needed to build a new model. One of the first things I did was add a Field mixin that would automatically enforce `blank=True` at the DB level. It `used contribute_to_class()` to add a constraint to `cls._meta.constraints()` which worked during testing with `pytest --nomigrations` but failed when using the migration. I’d also like to automatically create constraints for choice types as discussed above, just haven’t got there yet.

I eventually tracked this down to the constraints not being created in the migration if `Meta.constraints` was not defined on the model.

> [@nessita](#):
>
> So for this item, the main question is do we consider this a bug? From #28888 likely not since there is no documented support for adding indexes (or constraints) in `Field.contribute_to_class`, but it’s worth asking the question.

The documentation for `contribute_to_class()` is very minimal. I’ve only found [a wiki page](https://code.djangoproject.com/wiki/DevModelCreation) and a reference to it in the [model instance reference](https://docs.djangoproject.com/en/5.0/ref/models/instances/#django.db.models.Model.get_previous_by_FOO). But, it is mentioned and it is indicated that it can be used by developers, i.e. its not a private implementation.

Additionally, given a) that `._meta` is almost universally documented as the way to interact with `Meta` once the class has been created and b) constraints added by `contribute_to_class()` are recognized by other Django machinery as evidenced by their creation when using `pytest --nomigrations`, I believe it should be considered a bug that `makemigrations` does not create them.

Thanks for your consideration.

---

<div class="post-metadata">

**Author:** ![carltongibson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/carltongibson/32/267_2.png) [@carltongibson](https://forum.djangoproject.com/u/carltongibson)\
**Post date:** [January 19, 2024, 6:48pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/13 "2024-01-19T18:48:11Z")

</div>

I think there’s a case for this. E.g. adding a check constraint for (Text) Choices (say) would be in line with lots of the recent changes about pushing work down into the DB.

---

<div class="post-metadata">

**Author:** ![rsyring](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/rsyring/32/18554_2.png) [@rsyring](https://forum.djangoproject.com/u/rsyring)\
**Post date:** [January 19, 2024, 6:49pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/14 "2024-01-19T18:49:15Z")

</div>

Another reason to consider it a bug. If you add `constraints = ()` to `Meta` but then add the constraints dynamically to `_meta.constraints` then `makemigrations` will generate them. This resulted for me in a very weird scenario where one model’s dynamic constraints were being generated just fine (because it defined other static constraints in Meta) and another model’s dynamic constraints missing (b/c it defined no static constraints).

FWIW, I’m running v3.2.18 so its possible more recent versions of Django behave differently now.

I’ve worked around it by enforcing the presence of `Meta.constraints`:

```python
class TWTModelBase(models.base.ModelBase):
    def __new__ (cls, name, bases, attrs):

        # Ensures that TWModel instances have a Meta class with a 'constraints' attribute. Django
        # migrations have a bug that results in constraints not being generated if Meta or 
        # Meta.constraints is not present.
        attr_meta = attrs.get('Meta', type('Meta', (), {}))
        if not hasattr(attr_meta, 'constraints'):
            attr_meta.constraints = ()
            attrs['Meta'] = attr_meta

        new_cls = super(). __new__ (cls, name, bases, attrs)
        return new_cls

class TWTModel(models.Model, metaclass=TWTModelBase):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = Manager()

    class Meta:
        abstract = True

```

---

<div class="post-metadata">

**Author:** ![carltongibson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/carltongibson/32/267_2.png) [@carltongibson](https://forum.djangoproject.com/u/carltongibson)\
**Post date:** [January 19, 2024, 7:25pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/15 "2024-01-19T19:25:59Z")

</div>

It’s not clear to me that dynamically editing constraints yourself is supported. (Like, it’s possible but we may not want to draw conclusions from it.)

---

<div class="post-metadata">

**Author:** ![rsyring](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/rsyring/32/18554_2.png) [@rsyring](https://forum.djangoproject.com/u/rsyring)\
**Post date:** [January 19, 2024, 8:36pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/16 "2024-01-19T20:36:15Z")

</div>

> I’ve worked around it by enforcing the presence of `Meta.constraints`:

Turns out that even with the presence of Meta.constraints, I ran into a weird issue where running a migration that looked correct resulted in “constraint already exists” error for one, but only one of about five, constraints that were added dynamically.

I decided to punt on this implementation and just do it all with meta programming so that the constraints were added to `Meta.constraints` before `ModelBase. __new__ ()` is called.

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [September 15, 2024, 3:10am UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/17 "2024-09-15T03:10:34Z")

</div>

Do you have any examples?  
I’m stuck on this problem.

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [September 18, 2024, 12:42am UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/18 "2024-09-18T00:42:41Z")

</div>

This is the solution I came up with, so far I have no problems with it and it works.

```auto
class PositivoComun:

    @staticmethod
    def get_constrain(cls, name, minimo=0):
        return models.CheckConstraint(
                check=models.Q(**{f"{name}__gte": minimo}),
                name=f"check_{cls.lower()}_{name}_gte_{minimo}"
            )

class PositivoDecimalField(models.DecimalField, PositivoComun):
    """Campo de tipo decimal que solo permite números iguales o mayores a cero.
    """
    description = "Número decimal positivo"
    valor_minimo = 0

    def __init__ (self, *args, **kwargs):
        if 'valor_minimo' in kwargs:
            self.valor_minimo = kwargs['valor_minimo']
            del kwargs['valor_minimo']
        if 'default' not in kwargs:
            kwargs["default"] = 0
        if 'max_digits' not in kwargs:
            kwargs["max_digits"] = 18
        if 'decimal_places' not in kwargs:
            kwargs["decimal_places"] = 6
        if 'validators' not in kwargs:
            kwargs['validators'] = [MinValueValidator(self.valor_minimo), MaxValueValidator(999999999999)]
        super(). __init__ (*args, **kwargs)

class CustomModelMetaClass(ModelBase):
    def __new__ (cls, name, bases, attrs):
        klas = super(). __new__ (cls, name, bases, attrs)
        for f in attrs:
            if hasattr(attrs[f], "get_constrain") and callable(attrs[f].get_constrain):
                if hasattr(attrs[f], "valor_minimo"):
                    klas._meta.constraints.append(
                        attrs[f].get_constrain(klas. __name__ , f, attrs[f].valor_minimo)
                    )
                else:
                    klas._meta.constraints.append(
                        attrs[f].get_constrain(klas. __name__ , f)
                    )

        return klas

class AlmacenProducto(Modelos, metaclass=CustomModelMetaClass):
    existencia = PositivoDecimalField(db_column='existencia', blank=False, null=False, verbose_name='existencia')

```

---

<div class="post-metadata">

**Author:** ![Krozark](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/krozark/32/24364_2.png) [@Krozark](https://forum.djangoproject.com/u/Krozark)\
**Post date:** [October 4, 2024, 2:38pm UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/19 "2024-10-04T14:38:15Z")

</div>

the combination of metaclass + addind field.get\_constrain() works fine for me as well

```auto

class CustomModelMetaClass(ModelBase):
    def __new__ (cls, name, bases, attrs):
        klass = super(). __new__ (cls, name, bases, attrs)
        for field in attrs:
            if hasattr(attrs[field], "get_constrain") and callable(
                attrs[field].get_constrain
            ):
                klass._meta.constraints.append(
                    attrs[field].get_constrain(
                        klass._meta.app_label, klass._meta.model_name, field
                    )
                )
        return klass

class CustomFieldWithConstraint(Field):
    @staticmethod
    def get_constrain(app_label, model_name, field_name):
        return CheckConstraint(
            name=f"{app_label} __{model_name}__ {field_name}_...",
            check=... # whatever
        )

class Pole(Model, metaclass=CustomModelMetaClass):
    location = CustomFieldWithConstraint()

```

this create the correct migration with explicit DB constraint for the model

---

<div class="post-metadata">

**Author:** ![schinckel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/schinckel/32/111_2.png) [@schinckel](https://forum.djangoproject.com/u/schinckel)\
**Post date:** [February 20, 2025, 6:17am UTC](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934/20 "2025-02-20T06:17:30Z")

</div>

I’m still working through a similar issue (on Django 4.2), where I am getting weirdness around a constraint that a field was adding (in contribute\_to\_class). It appears to only occur when the field is used on an abstract model (and then that is then subclassed into a concrete model).

In that instance, the CreateModel() operation applies the constraint, but the migrations framework also generates a distinct AddConstraint operation.

[Next page](https://forum.djangoproject.com/t/dynamically-populate-constraints-in-field-contribute-to-class/22934.md?page=2)
