noo*_*zie 43 python django postgresql model
我基本上有一个用户名是唯一的(不区分大小写),但在用户提供的显示时,情况很重要.
我有以下要求:
Django有可能吗?
我想出的唯一解决方案是"以某种方式"覆盖模型管理器,使用额外的字段,或者总是在搜索中使用'iexact'.
我在Django 1.3和PostgreSQL 8.4.2上.
Ali*_*ani 32
截至 2021 年 12 月,借助Django 4.0 UniqueConstraint 表达式,您可以向模型添加 Meta 类,如下所示:
class Meta:
constraints = [
models.UniqueConstraint(
Lower('<field name>'),
name='<constraint name>'
),
]
Run Code Online (Sandbox Code Playgroud)
我绝不是 Django 专业开发人员,我不了解此解决方案的技术考虑因素,例如性能问题。希望其他人对此发表评论。
Erw*_*ter 26
将原始的大小写混合字符串存储在纯文本列中.使用数据类型text或varchar不使用长度修饰符而不是varchar(n).它们本质上是相同的,但是使用varchar(n)你必须设置一个任意长度限制,如果你想稍后改变,这可能会很痛苦.请阅读Peter Eisentraut @ serverfault.SE 手册或相关答案中的更多相关内容.
创建一个功能独特的指数上lower(string).这是主要观点:
CREATE UNIQUE INDEX my_idx ON mytbl(lower(name));
Run Code Online (Sandbox Code Playgroud)
如果您尝试以INSERT小写形式存在的混合大小写名称,则会出现唯一的密钥违例错误.
对于快速相等搜索,请使用如下查询:
SELECT * FROM mytbl WHERE lower(name) = 'foo' --'foo' is lower case, of course.
Run Code Online (Sandbox Code Playgroud)
使用索引中的相同表达式(以便查询计划程序识别兼容性),这将非常快.
暂且不说:您可能希望升级到更新版本的PostgreSQL.自8.4.2以来,已经有很多重要的修复.更多关于官方Postgres版本网站.
Rod*_*olz 24
从Django 1.11开始,您可以使用CITextField,这是一个Postgres特定的字段,用于由citext类型支持的不区分大小写的文本.
from django.db import models
from django.contrib.postgres.fields import CITextField
class Something(models.Model):
foo = CITextField()
Run Code Online (Sandbox Code Playgroud)
在Django中还提供了CIEmailField和CICharField,这是不区分大小写的版本EmailField和CharField.
Chr*_*att 18
通过覆盖模型管理器,您有两种选择.首先是创建一个新的查找方法:
class MyModelManager(models.Manager):
def get_by_username(self, username):
return self.get(username__iexact=username)
class MyModel(models.Model):
...
objects = MyModelManager()
Run Code Online (Sandbox Code Playgroud)
然后,你使用get_by_username('blah')而不是get(username='blah'),你不必担心忘记iexact.当然那要求你记得使用get_by_username.
第二种选择更加黑客和令人费解.我甚至对它的建议犹豫不决,但为了完整起见,我将:覆盖filter并且get如果你忘记iexact用户名查询,它会为你添加它.
class MyModelManager(models.Manager):
def filter(self, **kwargs):
if 'username' in kwargs:
kwargs['username__iexact'] = kwargs['username']
del kwargs['username']
return super(MyModelManager, self).filter(**kwargs)
def get(self, **kwargs):
if 'username' in kwargs:
kwargs['username__iexact'] = kwargs['username']
del kwargs['username']
return super(MyModelManager, self).get(**kwargs)
class MyModel(models.Model):
...
objects = MyModelManager()
Run Code Online (Sandbox Code Playgroud)
由于用户名总是小写,建议在 Django 中使用自定义的小写模型字段。为了便于访问和代码整洁,请fields.py在您的应用程序文件夹中创建一个新文件。
from django.db import models
from django.utils.six import with_metaclass
# Custom lowecase CharField
class LowerCharField(with_metaclass(models.SubfieldBase, models.CharField)):
def __init__(self, *args, **kwargs):
self.is_lowercase = kwargs.pop('lowercase', False)
super(LowerCharField, self).__init__(*args, **kwargs)
def get_prep_value(self, value):
value = super(LowerCharField, self).get_prep_value(value)
if self.is_lowercase:
return value.lower()
return value
Run Code Online (Sandbox Code Playgroud)
使用中models.py
from django.db import models
from your_app_name.fields import LowerCharField
class TheUser(models.Model):
username = LowerCharField(max_length=128, lowercase=True, null=False, unique=True)
Run Code Online (Sandbox Code Playgroud)
尾注:您可以使用此方法将小写值存储在数据库中,而不必担心__iexact.
| 归档时间: |
|
| 查看次数: |
15087 次 |
| 最近记录: |