2017-02-07 10 views
0

が自動的に入力された固定長のランダムな識別子であるべきフィールドを持つモデルがありますこの実装で参照フィールドのデフォルトの機能が

def save(self, *args, **kwargs): 
    if not self.pk: 
     while Post.objects.filter(identifier=self.identifier).exists(): 
      self.identifier = get_random_string_fixed() 
    super().save(*args, **kwargs) 

問題はget_random_string_fixedsave()方法でハードコードされていることである。そのような値が既に存在する場合、私は、Saveメソッドでそれを再生成します。ある時点で、このフィールドに別のデフォルト関数を選択することにした場合は、いくつかの場所でそれを変更する必要がありますが、これは悪い習慣です。

関数名をハードコーディングせずに、モデルのメソッドのフィールドのdefault属性に割り当てられた関数を参照する方法はありますか?

+0

'identifier_default'という名前の関数を作成し、それを代わりに使用します。実際の機能を好きな機能に委譲することができます。 – Selcuk

+0

ありがとう、これは本当にオプションですが、私は 'class.field.default'のようなものを介して取得する方法があることを願っています。 – BartoNaz

+0

なぜ 'while'は' get_random_string_fixed() 'の関数の中に置かれませんか? –

答えて

2

あなたがそれを行うためにintrospection APIを使用することができ、確かに:

Post._meta.get_field("identifier").default 

私は全くdefaultを有する点で多くのポイントが表示されていない、と述べました。とにかくsave()でそれを上書きしています。実際にはではないので、少し誤解を招くことがあります。

あなたのアルゴリズムにはまだ失敗のケースがあります。デフォルトのトランザクション分離レベルでは、2つのトランザクションが同じ値を同時に書き込むことを防ぎません。もちろん、それは非常にありそうもありません。

+0

ありがとう、提案のためにたくさん。一致した孤立した取引についてもっと詳しく説明できますか?どのようにしてそれらを守ることができますか? – BartoNaz

+0

デフォルトでは、トランザクションはオープンされた時点のデータベースの状態のみを表示します。したがって、トランザクションを開いた後に別のトランザクションが値 'X'を保存した場合、検索に' X'が表示されません。ただし、トランザクションをコミットしようとすると、一意制約のために失敗します。これらの問題を扱うことは簡単ではありませんが、可能な解決策については楽観的な並行性*を見ることができます。 –

+0

しかし、私のアドバイスは*これらの競合を検出することについて心配していません*。 UUID(基本的にあなたがやっていることです)を使用することの全ポイントは、衝突の可能性が天文学的に低いことです(https://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions)。それを無視します。私たちはそれに取り組んでいますが、組み込みの['UUIDField'](https://docs.djangoproject.com/ja/dev/ref/models/fields/#uuidfield)を使ってみませんか? –

関連する問題