验证模型字段是唯一的小写

时间:2021-08-09 11:51:50

I needed to validate a model field to be unique as lower case, but without actually saving the model field in lower case; e.g. if someone has already taken the username 'david', then the username 'David' would not be available. I tried various things, and eventually ended up doing the following:

我需要验证一个模型字段作为小写的唯一,但没有实际保存模型字段为小写;例如如果某人已经使用了用户名'david',则用户名'David'将无法使用。我尝试了各种各样的东西,最终最终做了以下事情:

def _perform_unique_checks(self, unique_checks):
    errors = {}

    for model_class, unique_check in unique_checks:

        lookup_kwargs = {}
        for field_name in unique_check:
            f = self._meta.get_field(field_name)
            lookup_value = getattr(self, f.attname)
            if lookup_value is None:
                continue
            if f.primary_key and not self._state.adding:
                continue
            lookup_kwargs[str(field_name)] = lookup_value

        if len(unique_check) != len(lookup_kwargs):
            continue

        if 'username' in lookup_kwargs:
            lookup_kwargs['username'] = lookup_kwargs['username'].lower()

        qs = model_class._default_manager.filter(**lookup_kwargs)

        model_class_pk = self._get_pk_val(model_class._meta)
        if not self._state.adding and model_class_pk is not None:
            qs = qs.exclude(pk=model_class_pk)
        if qs.exists():
            if len(unique_check) == 1:
                key = unique_check[0]
            else:
                key = NON_FIELD_ERRORS
            errors.setdefault(key, []).append(
                self.unique_error_message(model_class, unique_check))

... which works, but feels a little convoluted to me. I wondered whether any there's a more succinct way of achieving this?

......哪个有效,但对我来说感觉有点复杂。我想知道是否有更简洁的方法来实现这一目标?

2 个解决方案

#1


1  

Have you tried filtering on field_name__iexact, to do a case insensitive match?

您是否尝试过对field_name__iexact进行过滤,以进行不区分大小写的匹配?

The iregex, icontains and iexact filters should be able to do what you need.

iregex,icontains和iexact过滤器应该能够满足您的需求。

#2


0  

First off, you can user the clean for this functionality (triggered when trying to validate a form):

首先,您可以使用clean来实现此功能(在尝试验证表单时触发):

def clean__field_name(self):

Also, you can add a unique=True constraint to the field in question. Then do a Try/Except during save to catch any IntegrityError which will tell you that the field is not unique. The database and model should do this work for you instead of trying to code around it.

此外,您可以向相关字段添加unique = True约束。然后在保存期间执行Try / Except以捕获任何IntegrityError,它将告诉您该字段不是唯一的。数据库和模型应该为您完成这项工作,而不是尝试围绕它编写代码。

Also see Case insensitive unique model fields in Django?

另请参阅Django中的Case不敏感的唯一模型字段?

With more detail (database type, copy of model, are you using a Form?), I can expand on this answer.

有了更多的细节(数据库类型,模型的副本,你使用的是表单?),我可以扩展这个答案。

#1


1  

Have you tried filtering on field_name__iexact, to do a case insensitive match?

您是否尝试过对field_name__iexact进行过滤,以进行不区分大小写的匹配?

The iregex, icontains and iexact filters should be able to do what you need.

iregex,icontains和iexact过滤器应该能够满足您的需求。

#2


0  

First off, you can user the clean for this functionality (triggered when trying to validate a form):

首先,您可以使用clean来实现此功能(在尝试验证表单时触发):

def clean__field_name(self):

Also, you can add a unique=True constraint to the field in question. Then do a Try/Except during save to catch any IntegrityError which will tell you that the field is not unique. The database and model should do this work for you instead of trying to code around it.

此外,您可以向相关字段添加unique = True约束。然后在保存期间执行Try / Except以捕获任何IntegrityError,它将告诉您该字段不是唯一的。数据库和模型应该为您完成这项工作,而不是尝试围绕它编写代码。

Also see Case insensitive unique model fields in Django?

另请参阅Django中的Case不敏感的唯一模型字段?

With more detail (database type, copy of model, are you using a Form?), I can expand on this answer.

有了更多的细节(数据库类型,模型的副本,你使用的是表单?),我可以扩展这个答案。