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

デフォルトでは、MySQL はLIKE文字列を大文字と小文字を区別せずに比較します。

編集:
照合に関する追加情報を提供してくれた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)';

REGEXP を使用するには。

これは、クエリセット文字列を変更することを意味します。

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

最適ではありませんが、クエリ文字列を上下させてから、数字と英数字以外の文字用にまったく新しいクエリセットを作成する必要があります。

于 2010-04-09T21:25:41.637 に答える
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 に答える
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 に答える