Django 1.8 ArrayFieldを含む新しい高度なフィールドタイプが付属します これらはPostgreSQLに依存し、DBレベルで実装されます。
PostgreSQLの配列フィールド 追加メソッドを実装します 。
ただし、アイテムをArrayField
に追加するためのドキュメントが見つかりません。これは、コンテンツ全体をデータベースから転送してからフィールドに戻すことなくフィールドを更新できるため、明らかに非常に便利です。
これは可能ですか?そうでなければ、将来的には可能でしょうか?私が見逃したドキュメントへのポインタは大歓迎です。
私が何を求めているのかを明確にするために、これは素晴らしいことです:
注:これはファンタジーコードであり、機能しないと思います(試したことはありません)
# on model:
class Post(models.Model):
tags = ArrayField(models.CharField(max_length=200))
# somewhere else:
p = Post.objects.create(tags=[str(i) for i in range(10000)])
p.tags.append('hello')
現在、生のSQLに頼らずにこれを行う方法はありますか?
あなたが探している機能は現在実装されていないと思います(そして計画されていないかもしれません)。 Postgresの貢献機能の多く このキックスタータープロジェクトに基づいて作成されました 。
新機能の最も有用なドキュメントは ソースコード自体 から来ていると思います。これには、これらの機能の多くについて、元の プルリクエスト へのリンクが含まれています。
言及された配列関数に関する重要な注意点は、それらは関数であり、間違いなく 典型的なORMの範囲外 です。
この情報がお役に立てば幸いです。この問題に対する優れた解決策が見つかります。
注:OPコードは完全に機能します。モデルを保存する必要があります(これらは単なるモデルフィールドであり、リレーションではないため)。どれどれ:
>>> p = Post.objects.create(tags=[str(i) for i in range(10000)])
>>> p.tags.append("working!")
>>> p.save()
>>> working_post = Post.objects.get(tags__contains=["working!"])
<Post: Post object>
>>> working_post.tags[-2:]
[u'9999', u'working!']
ArrayField
をpython listあなたが でできる リストのすべて、あなたはArrayFieldで行うことができます。 並べ替えも
ArrayField
をpython list)として保存しますこれは、pythonリストの構造と要素を保存することを意味します。
これは機能します:
from Django.db.models import F
from Django.db.models.expressions import CombinedExpression, Value
post = Post.objects.get(id=1000)
post.tags = CombinedExpression(F('tags'), '||', Value(['hello']))
post.save()
または更新句で:
Post.objects.filter(created_on__lt=now() - timespan(days=30))\
.update(tags=CombinedExpression(F('tags'), '||', Value(['old'])))
別の解決策は、カスタム式を使用することです。次のコードをDjango 1.11およびPython 3.6(f-strings)でテストしました。
_from Django.db.models.expressions import Func
class ArrayAppend(Func):
function = 'array_append'
template = "%(function)s(%(expressions)s, %(element)s)"
arity = 1
def __init__(self, expression: str, element, **extra):
if not isinstance(element, (str, int)):
raise TypeError(
f'Type of "{element}" must be int or str, '
f'not "{type(element).__name__}".'
)
super().__init__(
expression,
element=isinstance(element, int) and element or f"'{element}'",
**extra,
)
_
この式はupdate()
で使用できます。
_Post.objects \
.filter(pk=1) \
.update(tags=ArrayAppend('tags', 'new tag'))
_
Django_postgres_extensions を使用できます。追加、追加、削除、連結などの多くの機能をサポートしています。
しかし、私のようにDjango 1.8を使用している場合は、このパッケージの必要なクラスのみを使用する必要があります。そうすれば、データベースバックエンドも変更する必要がありません。必要なものを貼り付けましたクラス ここ 。最初のリンクで説明されているように使用します。