40

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

class Ticket(models.Model):
    title = models.CharField()
    merged_to = models.ForeignKey("self", related_name='merger_ticket', null=True, blank=True)
    looser_ticket = models.BooleanField(default=False)

モデルを操作する方法はいくつかあります。

初め

ticket = Ticket.objects.get(pk=1)
ticket.title = "This is edit title"
ticket.merged_to_id = 2
ticket.looser_ticket = True

2番

ticket = Ticket.objects.get(pk=1)
setattr(ticket, "title", "Edit Title")
setattr(ticket, "merged_to_id", 2)
setattr(ticket, "looser_ticket", True)

私がものを操作していたとき、ブール値の更新の観点から、最初の方法は機能しませんでしたが、2番目の方法は機能しました。1番目と2番目の使用の違いは何ですか、またいつ使用する必要がありますか?

ありがとう!

4

2 に答える 2

52

これはPythonの質問です。

Pythonは非常に動的な言語です。事前に物事(クラス)をコーディングすることも、Pythonを使用して実行時に完全に動的にクラスを作成することもできます。次の単純なベクトルクラスの例を考えてみましょう。次のように、事前にクラスを作成/コーディングできます。

class MyVector(object):
    x = 0
    y = 0

または、次のようにしてクラスを動的に作成できます。

fields = {'x':0, 'y':0}
MyVector = type('MyVector', (object,), fields)

メソッド間の主な違いは、1つはクラス属性を事前に知っているのに対し、2つ目のメソッドはプログラムでfields辞書を作成できるため、完全に動的にクラスを作成できることです。

したがって、クラスの属性を事前に知っている場合は、オブジェクト表記を使用してクラス属性を設定できます。

instance.attribute = value

これは次と同等であることに注意してください。

instance.__setattr__("attribute", value)

ただし、事前に操作する必要があるクラス属性がわからないシナリオがあります。ここで関数を使用でき__setattr__ます。ただし、これはお勧めできません。setattrしたがって、代わりに、メソッドを内部的に呼び出すPythonの組み込みメソッドを使用することをお勧めします__setattr__

setattr(instance, attribute, value)

このアプローチを使用すると、事前にわからない属性を設定したり、いくつかのループをdict作成してdictから値を設定したりすることができます。

values = {
    'title': 'This is edit title',
    ...
}
for k, v in values.items():
    setattr(ticket, k, v)

通常の表記が機能しなかった理由がわかりません。おそらく、属性を設定するために使用した方法とは何の関係もありません。

于 2012-10-09T14:09:09.830 に答える
10

オブジェクトのプロパティを事前に知っている場合は、おそらく最初の方法を使用する必要があります。プロパティ値を直接割り当てるだけです。

2つ目は、プロパティに値を動的に割り当てる必要がある場合に役立ちます。おそらく、ユーザーはいくつかの異なる属性の値を変更することができ、どの属性が事前に値を持つかわからない場合は、動的に値を追加できます

possible_fields = ['title', 'looser_ticket']
ticket = Ticket.objects.get(pk=1)
for field in possible_fields:
  if request.GET.get(field):
     setattr(ticket, field, request.GET[field])

「機能しない」というのは、値の設定方法に依存していない可能性がありますが、後で変更を保存したことを確認しますか?

于 2012-10-09T13:50:38.610 に答える