In my models.py file I defined the following class:
class Space(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
node = models.ForeignKey(Node, on_delete=models.CASCADE, related_name='spaces', related_query_name='space')
nav_link = models.ForeignKey(NavLink, on_delete=models.CASCADE, related_name='space_nav_links', related_query_name='space_nav_link')
...
class Meta:
constraints = [
models.UniqueConstraint(fields=['node', 'nav_link'], name='unique_space')
]
I learned that Model constraints are “applied” at the time the model is attempting to be saved and that if I want to ensure that this doesn’t throw an IntegrityError I have to create a custom clean()
method in forms.py
class SpaceForm(ModelForm):
class Meta:
model = models.Space
fields = (
'nav_link',
)
def clean(self):
cleaned_data = super().clean()
nav_link_id = cleaned_data.get('nav_link')
if models.Space.objects.filter(node_id=self.user.node_id, nav_link_id=nav_link_id)).exists():
raise ValidationError(message='Space already exists. Please enter a unique space', code='invalid')
In a CreateView this works, however, in an UpdateView it raises the exception.
I thought adding `id’ to the filter would solve the issue:
if models.Space.objects.filter(~Q(id=id) & Q(node_id=self.user.node_id) & Q(nav_link_id=nav_link_id)).exists():
raise ValidationError(message='Space already exists. Please enter a unique space', code='invalid')
The issue here is, in case of a CreateView there is no id
and in case of an UpdateView the form doesn’t contain the id
.
My question is, is there a way to solve this issue?