#35848: Problem with UniqueConstraint on fields, one of which allows NULL value.
-------------------------------------+-------------------------------------
Reporter: Андрей | Owner: (none)
Type: Bug | Status: closed
Component: Database layer | Version: 5.1
(models, ORM) | Resolution:
Severity: Normal | worksforme
Keywords: UniqueConstraint, | Triage Stage:
nullable, null | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Андрей):
You are right that when Django is running through the SHELL, the error is
not reproduced (I checked it too after your message).
However, there is an error when creating an object using the rest api.
The order is as follows:
1. Create any ''measure'' object (m1. **This can be created using shell**
).
2. Create ''mymodel'' with the parameter measure = null (name="test".
**This can be created using shell** ).
3. Create ''mymodel'' from rest api (name="test", parameter=m1. **This
should be created via the viewset, in our case the rest api via
postman/bruno** ).
I get the error:
{{{
{
"name": [
"my model with that name already exists."
]
}
}}}
My scripts:
**models.py**
{{{
from django.db import models
from django.db.models import Q
class Measure(models.Model):
id = models.AutoField(
primary_key=True,
verbose_name="Key",
)
code = models.CharField(
max_length=5,
unique=True,
verbose_name="Code",
error_messages={"unique": "Err msg."},
)
def __str__(self):
return self.code
class MyModel(models.Model):
id = models.BigAutoField(primary_key=True, editable=False)
name = models.CharField(max_length=1000, verbose_name="Name")
measure = models.ForeignKey(
Measure,
related_name="mymodel_measure",
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name="Measure",
)
def __str__(self):
return
self.name
class Meta:
constraints = [
models.UniqueConstraint(
fields=["name"],
name="mymodel_unique_name_measure_null",
condition=Q(measure__isnull=True),
violation_error_message="Error message for null",
),
models.UniqueConstraint(
fields=["name", "measure"],
name="mymodel_unique_name_measure_not_null",
condition=Q(measure__isnull=False),
violation_error_message="Error message for not null",
),
]
}}}
**views.py**
{{{
from rest_framework import viewsets
from directories.serializers import MyModelSerializer
from .models import MyModel
class MyModelViewSet(viewsets.ModelViewSet):
queryset = MyModel.objects.select_related("measure").all()
serializer_class = MyModelSerializer
}}}
**serializers.py**
{{{
from rest_framework import serializers
from directories.models import MyModel
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = "__all__"
}}}
**urls.py**
{{{
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from directories.views import MyModelViewSet
router = DefaultRouter()
router.register("mymodel", MyModelViewSet)
urlpatterns = [
path("d/", include(router.urls)),
]
}}}
Next in postman or bruno create object (step 3):
post method, body:
{{{
{
"name": "test",
"measure": 1
}
}}}
and I get an error:
{{{
{
"name": [
"my model with that name already exists."
]
}
}}}
--
Ticket URL: <
https://code.djangoproject.com/ticket/35848#comment:4>