0

I have original question here How to access the names of fields in Django UniqueConstraint? but it do not answer my question when *expressions contains different kind of "fields". I left the accepted answer.


I want to access the unique constraint field names when declared in Meta class :

class Book(models.Model):
    name = CharField(...)
    author = ForeignKey(...)
    description = ...

    class Meta:
        constraints = [
            UniqueConstraint(
                Lower("name"), "author",
                name="unique__book_author",
            ),
        ]

    def do(self):
        unique_fields = ...  # should be ["name", "author"]

All fields are not necessarily a function like Lower. In this case, author is a foreign key.

See https://docs.djangoproject.com/en/4.1/ref/models/constraints/

cedrik
  • 541
  • 7
  • 17

1 Answers1

1

Idea

  1. Get constraints via model._meta.constraints
  2. Filter only unique constraints
  3. For each unique constraint, do the following
    1. If it does not contain expressions, get the field names from constraint.fields.
    2. Otherwise, get a field name from each expression by using expression.deconstruct() method.

Solution

from django.db import models


def get_unique_constraint_fields(model):
    unique_constraints = (
        c for c in model._meta.constraints
        if isinstance(c, models.UniqueConstraint)
    )
    fields = []
    for constraint in unique_constraints:
        if not constraint.contains_expressions:
            fields.extend(constraint.fields)
        else:
            for expression in constraint.expressions:
                # deconstruct() returns (path, fields, kwargs)
                _, (field, ), _ = expression.deconstruct()
                fields.append(field)
    return fields
annonymous
  • 741
  • 3
  • 6