13

I am trying to achieve a category model where name has unique=True, but practically I can still add same category name with different cases.

i.e. I have a category called Food I am still able to add food, FOOD, fOod, FOOd

Is their any philosophy behind this? or it is a work in progress.

Cause in real world if I think of Category Food, it will always be food, no matter what case it has used to mention itself.

Thank you in advance to look at this.

mmrs151
  • 3,924
  • 2
  • 34
  • 38

3 Answers3

23

To answer my own question:

I have found I can have clean method on my model. So I added

class Category(models.Model):
    name = models.CharField(max_length=200, unique=True)

    def clean(self):
        self.name = self.name.capitalize()

It is capitalising the first letter, which is then handled by the save method, which calls the validate_unique method to raise error.

mmrs151
  • 3,924
  • 2
  • 34
  • 38
2

You can use Postgre specific model field called Citext fields (case insensitive fields).

There are three option at the moment:

class CICharField(**options), class CIEmailField(**options) and class CITextField(**options)

Example:

from django.db import models

from django.contrib.postgres.fields import CICharField


class Category(models.Model):
    name = CICharField(verbose_name="Name", max_length=255)

But don't forget to create an extension for the citext fields. See here.

Basically, you have to add the extension class in the migration file, inside the operations array, before the first CreateModel operation.

# migration file

    operations = [
        CITextExtension(),        # <------ here
        migrations.CreateModel(
            ...
        ),
        ...,
    ]

Öykü
  • 252
  • 1
  • 3
  • 13
-2

Setting the column to case-insensitive collation should fix this. You may need to do it at the SQL level.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358