2

私はこの種のパターンを何度も繰り返します:(そして私はこれは一般的ではないと思いますか?)

Google App Engine

# Insert if object doesn't exist, Otherwise Update Object
obj = get_or_insert('123', title='Hello World')
obj.title = 'Hello World'
obj.puts()

Django

# Insert if object doesn't exist, Otherwise Update Object
obj, created = Model.objects.get_or_create(id='123', 
                   defaults={'title':'Hello World'}
if not created:
    obj.title = 'Hello World'
    obj.save()

ただ電話できたらいいのに。ではない?例えば:insert_or_update

# AppEngine
obj = insert_or_update('123', title='Hello World')

# Django
obj = Model.objects.insert_or_update(id='123', defaults={'title': 'Hello World'})

アップデート

App Engineのドキュメントに戻ると、このget_or_insertメソッドの機能に関するスニペットが見つかりました。次のようなもの:

def txn(key_name, **kwds):
    entity = Story.get_by_key_name(key_name, parent=kwds.get('parent'))
    if entity is None:
        entity = Story(key_name=key_name, **kwds)
        entity.put()
    return entity

def get_or_insert(key_name, **kwargs):
    return db.run_in_transaction(txn, key_name, **kwargs)

get_or_insert('some key', title="The Three Little Pigs")

なぜinsert_or_updateアプリエンジンとdjangoの両方でメソッドが作成されないのか疑問に思いました。

AppEngineの回避策

@classmethod
def insert_or_update(cls, key_name, parent=None, **kwargs):
    def _tx():
        entity = cls.get_by_key_name(key_name, parent=parent)
        if entity:
            for key in kwargs:
                setattr(entity, key, kwargs[key])
        else:
            entity = cls(key_name=key_name, parent=parent, **kwargs)
        entity.put()
        return entity
    return db.run_in_transaction(_tx)

Djangoソリューション

下記参照

4

3 に答える 3

1

ジャンゴ

update_or_create (Django 公式ドキュメントより)

update_or_create(defaults=None, **kwargs)

Django 1.7 バージョンの新機能。

kwargs指定された でオブジェクトを更新し、必要に応じて新しいオブジェクトを作成する便利なメソッド。はdefaults、オブジェクトの更新に使用される (フィールド、値) ペアのディクショナリです。

のタプルを返します(object, created)。ここobjectで、 は作成または更新されたオブジェクトで、createdは新しいオブジェクトが作成されたかどうかを指定するブール値です。

このupdate_or_createメソッドは、指定された に基づいてデータベースからオブジェクトを取得しようとしますkwargsdefaults一致が見つかった場合は、ディクショナリに渡されたフィールドを更新します。

これはボイラープレート コードへのショートカットとして意図されています。例えば:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
    for key, value in updated_values.iteritems():
        setattr(obj, key, value)
    obj.save()
except Person.DoesNotExist:
    updated_values.update({'first_name': 'John', 'last_name': 'Lennon'})
    obj = Person(**updated_values)
    obj.save()

モデル内のフィールド数が増えると、このパターンは非常に扱いにくくなります。上記の例は、次のように書き直すことができますupdate_or_create()

obj, created = Person.objects.update_or_create(
    first_name='John', last_name='Lennon', defaults=updated_values)

kwargs で渡された名前がどのように解決されるかの詳細な説明については、 を参照してくださいget_or_create()

上記の で説明したようにget_or_create()、この方法では競合状態が発生しやすく、データベース レベルで一意性が強制されていない場合、複数の行が同時に挿入される可能性があります。

AppEngine

Matt が前に述べたように、まだそれほど幸運ではありませんが、これは一般的な使用例ではない可能性があります。おそらく、AppEngine では、そのような使用例はそれほど多くありません。

于 2013-12-06T17:45:33.220 に答える
0

質問を正しく理解した場合:

obj, created = Model.objects.get_or_create(id='123', 
               defaults={'title':'Hello World'})

上記は、次のように置き換える必要があります。

obj, created = Model.objects.get_or_create(foo='alpha', bar='beta' 
               defaults={'title':'Hello World'})

ここで、foobarはモデルのフィールドです。これにより、djangoの繰り返しが解決されます。appengineについて不明です。HTH

于 2013-02-27T17:11:41.870 に答える
0

おそらく、あなたが思っているほど一般的ではありません。個人的には、これを頻繁に行う必要はありません。実行すると、提案された方法よりも 2、3 行だけ長くなります。insert_or_updateこれでは、この機能を求めて叫んだり、追加する動機を与えたりするのに十分ではありません。自分。私は過去にMySQLをINSERT … ON DUPLICATE KEY UPDATEかなり使ってきましたが。

私自身、このような経験を数回経験しましたが、ほんの数週間前に、なぜ Django にはtoggleM2M 関係のメソッドがないのか疑問に思っていました...最終的に作成しました。

https://github.com/Matt-Stevens/django/commit/f7c36

編集

Django 1.7 には、この「UPSERT」機能があるようです。 https://github.com/django/django/commit/6272d

于 2013-02-27T18:10:30.753 に答える