THis is the raw query that I write for postgres for the check constraint
ALTER TABLE rea_asplinkage ADD CONSTRAINT asp_sub_project_positive_integer
CHECK (
jsonb_typeof(linkage-> 'root' -> 'in_sub_project') is not distinct from 'number'
and (linkage->'root'->>'in_sub_project')::numeric % 1 = 0
and (linkage->'root'->>'in_sub_project')::numeric > 0
);
And the way I create the migration is this way
# Generated by Django 2.2.10 on 2020-05-16 12:59
from django.db import connection, migrations
class Migration(migrations.Migration):
dependencies = [("rea", "0029_asplinkage")]
operations = [
migrations.RunSQL(
sql="""
ALTER TABLE rea_asplinkage ADD CONSTRAINT asp_sub_project_positive_integer
CHECK (
jsonb_typeof(linkage-> 'root' -> 'in_sub_project') is not distinct from 'number'
and (linkage->'root'->>'in_sub_project')::numeric % 1 = 0
and (linkage->'root'->>'in_sub_project')::numeric > 0
);
""",
reverse_sql="""
ALTER TABLE rea_asplinkage DROP CONSTRAINT "asp_sub_project_positive_integer";
""",
)
]
And this works.
But this means that my original model does not show the constraint in the class Meta
of the ASPLinkage model
class ASPLinkage(TimeStampedModel, SoftDeletableModel, PersonStampedModel, OrganizationOwnedModel):
linkage = JSONField(default=default_linkage_for_asp)
objects = OrganizationOwnedSoftDeletableManager()
I have tried ExpressionWrapper
and RawSQL
in creating the constraints inside the class Meta, but it still doesn't work.
For reference, I have looked at the examples found in https://github.com/django/django/blob/master/tests/constraints/models.py#L12
I have also looked at Separate Database and State migration via https://realpython.com/create-django-index-without-downtime/#when-django-generates-a-new-migration
But I still cannot get it to work
So is this even possible?
Update
Let me write a summary of my question for better readability.
- I want to write constraints on a JSONField.
- I can do that directly on the Postgres
- Therefore I can do it using raw sql in the migration file
- But I cannot do the equivalent using Django model meta / CheckConstraint which usually is how anyone does it. See https://docs.djangoproject.com/en/3.0/ref/models/constraints/
- So how do I rewrite this raw sql to produce constraint on a jsonfield in postgres but in the Django way?