1

我使用通用视图,并尝试以不区分大小写的方式查询我的 MySQL 数据库(utf8_bin 排序规则),以尝试查找以特定字母开头的所有歌曲标题。

view.py

def tracks_by_title(request, starts_with):
    return object_list(
        request,
        queryset = Track.objects.filter(title__istartswith=starts_with),
        template_name = 'tlkmusic_base/titles_list.html',
        template_object_name = 'tracks',
        paginate_by = 25,
    )

和我的

urls.py

urlpatterns = patterns('tlkmusic.apps.tlkmusic_base.views',
    (r'^titles/(?P<starts_with>\w)/$', tracks_by_title),
)

它根据 django 调试工具栏产生的查询是:

SELECT `tracks`.`id`, `tracks`.`url`, `tracks`.`artist`, `tracks`.`album`, `tracks`.`genre`, `tracks`.`year`, `tracks`.`title`, `tracks`.`comment`, `tracks`.`tracknumber`, `tracks`.`discnumber`, `tracks`.`bitrate`, `tracks`.`length`, `tracks`.`samplerate`, `tracks`.`filesize`, `tracks`.`createdate`, `tracks`.`modifydate` FROM `tracks` WHERE `tracks`.`title` LIKE a% LIMIT 1

特别是这一行:

WHERE `tracks`.`title` LIKE a% LIMIT 1

为什么它不区分大小写,这是我使用 __istartswith 所期望的?

我在 Ubuntu 上使用 Django 1.1.1。

编辑

在 phpmyadmin 中运行SELECT * FROM tracks WHERE title LIKE 'a%' LIMIT 0 , 30仍会返回区分大小写的结果,更改排序规则是我想要避免的,主要是因为数据库由 Amarok 维护,我不知道更改排序规则的结果。

4

4 回答 4

3

MySQL 不支持ILIKE.

默认情况下,MySQLLIKE不区分大小写地比较字符串。

编辑:
感谢 OP 提供有关排序规则的其他信息。
当前排序规则utf8_bin是区分大小写的。
相反,utf8_general_ci不区分大小写。

修改排序规则可能最容易。
像这样的东西:

ALTER TABLE `mydb`.`mytable` 
MODIFY COLUMN `song_title` VARCHAR(254) 
CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL;
于 2010-04-09T20:50:03.770 回答
2

一个解决方案,虽然不是我希望/期望的但仍然有效的是:

SELECT * FROM tracks WHERE title REGEXP BINARY '^(a|A)';

使用正则表达式。

这意味着更改我的查询集字符串。

queryset = Track.objects.filter(title__regex=r'^(a|A)'),

不是最优的我将不得不上下查询字符串,然后为数字和非字母数字字符编写一个全新的查询集。

于 2010-04-09T21:25:41.637 回答
0

该死的,我发现了另一种尴尬的方法。

from django.db.models import Q

queryset = Track.objects.filter(Q(title__startswith=starts_with.upper) | Q(title__startswith=starts_with.lower)),
于 2010-04-09T23:18:03.613 回答
0

我的解决方案是“扩展”查询集以覆盖某些行为(django 1.4):

# coding: UTF-8
from django.db.backends.mysql.base import DatabaseOperations as MySqlDatabaseOperations
from django.db.models.query import QuerySet
from django.db.models import sql
from django.db.models.sql.where import WhereNode


class ExtMySqlDatabaseOperations(MySqlDatabaseOperations):
    def lookup_cast(self, lookup_type):
        if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith'):
            return "LOWER(%s)"
        return super(ExtMySqlDatabaseOperations, self).lookup_cast(lookup_type)

class ExtWhereNode(WhereNode):

    def make_atom(self, child, qn, connection):
        lvalue, lookup_type, value_annotation, params_or_value = child
        if type(connection.ops) in (MySqlDatabaseOperations, ExtMySqlDatabaseOperations):
            if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith'):
                params_or_value = params_or_value.lower()
            connection.ops = ExtMySqlDatabaseOperations(connection)
        return WhereNode.make_atom(self, (lvalue, lookup_type, value_annotation, params_or_value), qn, connection)

class ExtQuerySet(QuerySet):
    def __init__(self, model=None, query=None, using=None):
        query = query or sql.Query(model, where = ExtWhereNode)
        super(ExtQuerySet, self).__init__(model = model, query = query, using = using)
        #self.query = self.query or sql.Query(model, where = ExtWhereNode)

def ext(qs):
    return ExtQuerySet(model=qs.model, using=qs._db)
于 2013-03-15T14:36:10.237 回答