私は次のモデルを持っています:
class Page(Model):
book = ForeignKey(Book, on_delete=CASCADE)
page = IntegerField()
start = CharField(max_length=350, db_index=True)
end = CharField(max_length=350, db_index=True)
特定の単語を「含む」ページを取得するために、DBにクエリを実行するにはどうすればよいですか?
page1 = Page.objects.create(start='beaver', end='brother')
page2 = Page.objects.create(start='boy', end='brother')
block
がアルファベット順にbeaverの前にあるため、唯一のpage1を返す必要があります兄弟。検索では大文字と小文字が区別されません。
したがって、すべての行をフェッチするクエリを作成する必要があります。ここで、start
は指定されたWordよりもアルファベット順で「小さい」、end
は指定されたWordよりアルファベット順で「大きい」です。
私の答えはPostgresqlにのみ適用されますが、ここに1つの解決策があります:
Postgresqlを使用したDjangoでは、_Django.contrib.postgres.fields
_にCICharField
モデルフィールドがあります。これは、大文字と小文字を区別しない文字列のインデックス作成もサポートします。文字列は大文字と小文字が正しく保存されますが、比較演算では大文字と小文字が区別されません。
_from Django.contrib.postgres.field import CICharField
class Page(Model):
book = ForeignKey(Book, on_delete=CASCADE)
page = IntegerField()
start = CICharField(max_length=350, db_index=True)
end = CICharField(max_length=350, db_index=True)
_
これで問題はほぼ解決されます。gte
およびlte
フィルターを使用でき、比較では大文字と小文字が区別されません。データベースの設定に応じて、Unicodeを適切に処理する必要があります。
_t1 = "breast"
t2 = "beast"
t3 = "block"
page1 = Page.objects.create(start='beaver', end='brother')
page2 = Page.objects.create(start='boy', end='brother')
Page.objects.filter(start__lte=t1, end__gte=t1) # <QuerySet [<Page: Page start=beaver, end=brother>, <Page: Page start=boy, end=brother>]>
Page.objects.filter(start__lte=t2, end__gte=t2) # <QuerySet []>
Page.objects.filter(start__lte=t3, end__gte=t3) # <QuerySet [<Page: Page start=beaver, end=brother>]>
t4 = "Ù" # Between Ø and Ú
t5 = "Ü" # Not between Ø and Ú
page3 = Page.objects.create(start='Ø', end='Ú')
Page.objects.filter(start__lte=t4, end__gte=t4) # <QuerySet [<Page: Page start=Ø, end=Ú>]>
Page.objects.filter(start__lte=t5, end__gte=t5) # <QuerySet []>
_
この変更により、データベースにCITextExtension()
をインストールして列を変更する移行が生成されます。 might移行ファイルを2つの移行に分離する必要があります。最初の移行ではCITextExtension
をインストールし、2番目の移行では既存の列を変更します。