且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Django中不区分大小写的独特模型字段?

更新时间:2022-12-18 13:31:35

将原始混合大小写字符串存储在纯文本列中。使用数据类型 文本 varchar 而不使用长度修饰符,而不是 VARCHAR(n)的。它们基本上是一样的,但是使用varchar(n),你必须设置一个任意的长度限制,如果你想稍后改变,这可能会很痛苦。详细了解手册或本相关答案由Peter Eisentraut @ serverfault.SE



创建一个 功能唯一索引 C $ C>下(字符串)。这是主要的一点:

  CREATE UNIQUE INDEX my_idx ON mytbl(lower(name)); 

如果您尝试 INSERT 这个名字已经在小写上,你会得到一个唯一的密钥违规错误。

对于快速的等式搜索使用这样的查询:

  SELECT * FROM mytbl WHERE lower(name)='foo' - 'foo'是小写的,当然。 

使用与索引中相同的表达式(因此查询计划程序可以识别兼容性)非常快。






另外,您可能需要升级到PostgreSQL的最新版本。自8.4.2以来,已有大量重要修复程序。有关官方Postgres版本控制网站的更多信息。


I have basically a username is unique (case insensitive), but the case matters when displaying as provided by the user.

I have the following requirements:

  • field is CharField compatible
  • field is unique, but case insensitive
  • field needs to be searchable ignoring case (avoid using iexact, easily forgotten)
  • field is stored with case intact
  • preferably enforced on database level
  • preferably avoid storing an extra field

Is this possible in Django?

The only solution I came up with is "somehow" override the Model manager, use an extra field, or always use 'iexact' in searches.

I'm on Django 1.3 and PostgreSQL 8.4.2.

Store the original mixed-case string in a plain text column. Use the data type text or varchar without length modifier rather than varchar(n). They are essentially the same, but with varchar(n) you have to set an arbitrary length limit, that can be a pain if you want to change later. Read more about that in the manual or in this related answer by Peter Eisentraut @serverfault.SE.

Create a functional unique index on lower(string). That's the major point here:

CREATE UNIQUE INDEX my_idx ON mytbl(lower(name));

If you try to INSERT a mixed case name that's already there in lower case you get a unique key violation error.
For fast equality searches use a query like this:

SELECT * FROM mytbl WHERE lower(name) = 'foo' --'foo' is lower case, of course.

Use the same expression you have in the index (so the query planner recognizes the compatibility) and this will be very fast.


As an aside: you may want to upgrade to a more recent version of PostgreSQL. There have been lots of important fixes since 8.4.2. More on the official Postgres versioning site.