Unique model field in Django and case sensitivity (postgres)

前端 未结 10 730
时光取名叫无心
时光取名叫无心 2020-12-13 13:37

Consider the following situation: -

Suppose my app allows users to create the states / provinces in their country. Just for clarity, we are considering only ASCII ch

相关标签:
10条回答
  • 2020-12-13 14:25

    On the Postgres side of things, a functional unique index will let you enforce unique values without case. citext is also noted, but this will work with older versions of PostgreSQL and is a useful technique in general.

    Example:

    # create table foo(bar text);
    CREATE TABLE
    # create unique index foo_bar on foo(lower(bar));
    CREATE INDEX
    # insert into foo values ('Texas');
    INSERT 0 1
    # insert into foo values ('texas');
    ERROR:  duplicate key value violates unique constraint "foo_bar"
    
    0 讨论(0)
  • 2020-12-13 14:30

    You can use lookup='iexact' in UniqueValidator on serializer, like this:

    class StateSerializer(serializers.ModelSerializer): 
        name = serializers.CharField(validators=[
        UniqueValidator(
            queryset=models.State.objects.all(),lookup='iexact'
        )]
    

    django version: 1.11.6

    0 讨论(0)
  • 2020-12-13 14:32

    You can do this by overwriting the Model's save method - see the docs. You'd basically do something like:

    class State(models.Model):
        name = models.CharField(max_length=50, unique=True)
    
        def save(self, force_insert=False, force_update=False):
            if State.objects.get(name__iexact = self.name):
                return
            else:
                super(State, self).save(force_insert, force_update)
    

    Also, I may be wrong about this, but the upcoming model-validation SoC branch will allow us to do this more easily.

    0 讨论(0)
  • 2020-12-13 14:36

    Besides already mentioned option to override save, you can simply store all text in lower case in database and capitalize them on displaying.

    class State(models.Model):
        name = models.CharField(max_length=50, unique=True)
    
        def save(self, force_insert=False, force_update=False):
            self.name = self.name.lower()
            super(State, self).save(force_insert, force_update)
    
    0 讨论(0)
提交回复
热议问题