Unique model field in Django and case sensitivity (postgres)

前端 未结 10 749
时光取名叫无心
时光取名叫无心 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:14

    If you don't want to use a postgres-specific solution, you can create a unique index on the field with upper() to enforce uniqueness at the database level, then create a custom Field mixin that overrides get_lookup() to convert case-sensitive lookups to their case-insensitive versions. The mixin looks like this:

    class CaseInsensitiveFieldMixin:
        """
        Field mixin that uses case-insensitive lookup alternatives if they exist.
        """
    
        LOOKUP_CONVERSIONS = {
            'exact': 'iexact',
            'contains': 'icontains',
            'startswith': 'istartswith',
            'endswith': 'iendswith',
            'regex': 'iregex',
        }
    
        def get_lookup(self, lookup_name):
            converted = self.LOOKUP_CONVERSIONS.get(lookup_name, lookup_name)
            return super().get_lookup(converted)
    

    And you use it like this:

    from django.db import models
    
    
    class CICharField(CaseInsensitiveFieldMixin, models.CharField):
        pass
    
    
    class CIEmailField(CaseInsensitiveFieldMixin, models.EmailField):
        pass
    
    
    class TestModel(models.Model):
        name = CICharField(unique=True, max_length=20)
        email = CIEmailField(unique=True)
    

    You can read more about this approach here.

提交回复
热议问题