# Django encrypted field + unique

**URL:** <https://forum.djangoproject.com/t/django-encrypted-field-unique/38950>\
**Category:** Mystery Errors\
**Created:** [February 18, 2025, 11:17pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950 "2025-02-18T23:17:49Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![djunior](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/djunior/32/26227_2.png) [@djunior](https://forum.djangoproject.com/u/djunior)\
**Post date:** [February 18, 2025, 11:17pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/1 "2025-02-18T23:17:49Z")

</div>

I want to use django\_cryptography.fields.encrypt in my model to have a field:

```auto
 sin = encrypt(models.IntegerField(
        validators=[MinValueValidator(10000000), MaxValueValidator(99999999)],
        default="",
        unique=True,
    ))

```

However, using unique with encrypt throws:

```auto
django.core.exceptions.FieldError: Unsupported lookup 'exact' for EncryptedBigIntegerField or join on the field not permitted, perhaps you meant exact or iexact?

```

This is on django 5.1. Any ideas or suggestions to fix this, maybe another way to encrypt the field?

---

<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:** [February 18, 2025, 11:48pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/2 "2025-02-18T23:48:08Z")

</div>

The `django_cryptography` project only shows as being tested up through Django 4.2 and python 3.11. It doesn’t show as being compatible with Django 5.1.

Also, according to [Django 5.x support? · Issue #115 · georgemarshall/django-cryptography · GitHub](https://github.com/georgemarshall/django-cryptography/issues/115), this appears like it may be an abandoned project. (The last public release was version 1.1 from 2022.)

You could fork the project and bring it up to date.

Check out [Django Packages : Encryption](https://djangopackages.org/grids/g/encryption/) for some other possible options.

---

<div class="post-metadata">

**Author:** ![djunior](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/djunior/32/26227_2.png) [@djunior](https://forum.djangoproject.com/u/djunior)\
**Post date:** [February 19, 2025, 1:18pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/3 "2025-02-19T13:18:03Z")

</div>

thanks for the response. I have also tried [GitHub - chrisclark/django-cryptography: Easily encrypt data in Django](https://github.com/chrisclark/django-cryptography) and [django-cryptography-5](https://pypi.org/project/django-cryptography-5/) which are both forks of the original django-cryptography though with not too many commits, however, the behaviour is the same.

Interestingly, the error occurs only when using the CreateView. Creating an instance by extracting the data from an uploaded file or via the shell, the constraint “unique” is completely ignored.

I will have a look at the django packages and we will see what I will come up with. I will keep this thread updated.

---

<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:** [February 19, 2025, 1:30pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/4 "2025-02-19T13:30:07Z")

</div>

Please provide the full error message with the traceback that you are receiving.

---

<div class="post-metadata">

**Author:** ![djunior](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/djunior/32/26227_2.png) [@djunior](https://forum.djangoproject.com/u/djunior)\
**Post date:** [February 19, 2025, 1:48pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/5 "2025-02-19T13:48:54Z")

</div>

voila:

```auto
Internal Server Error: /person/add
Traceback (most recent call last):
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/views/generic/edit.py", line 182, in post
    return super().post(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/views/generic/edit.py", line 150, in post
    if form.is_valid():
       ^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/forms/forms.py", line 197, in is_valid
    return self.is_bound and not self.errors
                                 ^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/forms/forms.py", line 192, in errors
    self.full_clean()
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/forms/forms.py", line 327, in full_clean
    self._post_clean()
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/forms/models.py", line 504, in _post_clean
    self.validate_unique()
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/forms/models.py", line 513, in validate_unique
    self.instance.validate_unique(exclude=exclude)
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/base.py", line 1378, in validate_unique
    errors = self._perform_unique_checks(unique_checks)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/base.py", line 1477, in _perform_unique_checks
    qs = model_class._default_manager.filter(**lookup_kwargs)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/query.py", line 1476, in filter
    return self._filter_or_exclude(False, args, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/query.py", line 1494, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/query.py", line 1501, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1609, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1641, in _add_q
    child_clause, needed_inner = self.build_filter(
                                 ^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1555, in build_filter
    condition = self.build_lookup(lookups, col, value)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1379, in build_lookup
    lhs = self.try_transform(lhs, lookup_name)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/zpool/work/dev/django/django-tinker/py311-dj51-pdf/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1423, in try_transform
    raise FieldError(
django.core.exceptions.FieldError: Unsupported lookup 'exact' for EncryptedIntegerField or join on the field not permitted, perhaps you meant exact or iexact?
[19/Feb/2025 14:43:25] "POST /person/add HTTP/1.1" 500 161198

```

---

<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:** [February 19, 2025, 2:03pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/6 "2025-02-19T14:03:32Z")

</div>

Thanks. (I wanted to acknowledge your post.)

This one looks interesting. Unfortunately, it’s going to take me a little bit of time to dig in to.

---

<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:** [February 19, 2025, 2:45pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/7 "2025-02-19T14:45:49Z")

</div>

Before I dive into this in more detail, is there any other potential relevant information?

For example, are you using a custom Manager class for this model?

Are you using any mixins in your model class definition?

Are you using any mixins in your CreateView? Any method decorators?

Are you overriding any of the view methods?

(It may be helpful if you posted the complete model and view.)

---

<div class="post-metadata">

**Author:** ![djunior](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/djunior/32/26227_2.png) [@djunior](https://forum.djangoproject.com/u/djunior)\
**Post date:** [February 19, 2025, 3:04pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/8 "2025-02-19T15:04:07Z")

</div>

it’s a very basic model and view, no manager/mixins/decorated functions:

```auto
class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    sin = encrypt(models.IntegerField(
            validators=[MinValueValidator(1000000000), MaxValueValidator(9999999999)],
            unique=True,
            default="",
        ))

    pnr = encrypt(models.IntegerField(
        validators=[MinValueValidator(0), MaxValueValidator(1000)],
        default="",
        unique=True,
    ))
    titel = models.CharField(max_length=16, blank=True, default="")
    firstname = models.CharField(max_length=18, default="")
    lastname = models.CharField(max_length=24, default="")
    birthdate = encrypt(models.DateField(blank=True, default=""))
    email = models.EmailField(blank=True, default="")
    phone = encrypt(models.CharField(max_length=18, blank=True, default=""))
    street = encrypt(models.CharField(max_length=28, blank=True, default=""))
    zip = encrypt(models.IntegerField(
            validators=[MinValueValidator(1000), MaxValueValidator(99999)],
            blank=True,
            default="",
    ))
    city = encrypt(models.CharField(max_length=28, blank=True, default=""))
    country = models.CharField(max_length=16, blank=True, default="")
    docpassword = encrypt(
        models.CharField(
            max_length=20,
            validators=[MinLengthValidator(12)],
            default=secrets.token_urlsafe(32)[:20],
        )
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural = "Personen"
        ordering = ["lastname"]

    def __str__ (self):
        return " ".join([str(self.firstname), str(self.lastname)])

    def get_absolute_url(self):
        return reverse("person_detail", kwargs={"pk": self.pk})

```

```auto
class PersonAddView(CreateView):
    model = Person
    template_name = "person_add.html"
    fields = (
       "sin",
       "pnr",
       "titel",
       "firstname",
       "lastname",
       "birthdate",
       "email",
       "phone",
       "street",
       "zip",
       "city",
       "country",
       "docpassword"
    )

```

---

<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:** [February 20, 2025, 1:06pm UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/9 "2025-02-20T13:06:35Z")

</div>

One thing I see right off-hand is that you’re trying to assign a null string as the default value of an integer field. I don’t know if it’s at all related to this issue, but it’s something that should be fixed.

> [@djunior](#):
>
> ```auto
> sin = encrypt(models.IntegerField(
> validators=[MinValueValidator(1000000000), MaxValueValidator(9999999999)],
> unique=True,
> default="",
> ^^ Not the right data type for this field.
> ))
> 
> ```

---

<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:** [February 21, 2025, 12:51am UTC](https://forum.djangoproject.com/t/django-encrypted-field-unique/38950/10 "2025-02-21T00:51:36Z")

</div>

What database engine are you using?

I use PostgreSQL, and while I’m also getting errors, it’s not the same errors as you’re getting. Since we’re both seeing errors in the ORM itself, I’m thinking that the difference may be related to the database being used.
