web-dev-qa-db-ja.com

文字列をアルファベット順に比較Django db

私は次のモデルを持っています:

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')
  • Page.objects.filter( "開始と終了の間の胸")は、ページ1とページ2を返す必要があります。
  • Page.objects.filter( "beast" between start and end)は何も返しません。
  • Page.objects.filter( "start"とendの間の "block")は、blockがアルファベット順にbeaverの前にあるため、唯一のpage1を返す必要があります兄弟

検索では大文字と小文字が区別されません。

したがって、すべての行をフェッチするクエリを作成する必要があります。ここで、startは指定されたWordよりもアルファベット順で「小さい」、endは指定されたWordよりアルファベット順で「大きい」です。

4
Andrew Fount

私の答えは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番目の移行では既存の列を変更します。

0
A. J. Parr