0

views.pyが持っている:

my_computer = Computer.objects.get(pk=some_value)

computer オブジェクトには、projects という名前のフィールドがあり、ManyRelatedManager.

通話中

my_projects = my_computer.projects.all()

の値をmy_projects3 つのプロジェクト オブジェクトのリストに設定します。

私が達成しようとしているのはmy_computer.projects、の代わりに上記のプロジェクトのリストにの値を設定することManyRelatedManagerです。

私が試してみました:

my_computer.projects = my_projects

エラーは発生しませんが、それは機能しません。の値my_computer.projectsはまだManyRelatedManagerです。

4

2 に答える 2

1

Managerオブジェクトの実装__set__- それらは記述子として動作します。

これは、割り当てによってオブジェクトを変更できないことを意味します (別のオブジェクトの属性が親オブジェクト__set__のコンテキストでのみ呼び出される限り、継承関係ではなく、構成関係に関する親)。__setattr__

そのような反復可能な値が期待されるタイプのモデルを生成する場合、リストのような (実際には: 反復可能な) 値をマネージャーに割り当てることができます。ただし、これは次のことを意味します。

  1. を照会my_computer.projectsすると、割り当てたオブジェクトを含むマネージャー オブジェクトが再び取得されます。
  2. オブジェクトを保存するmy_computerと、指定したオブジェクトのみがリレーションシップに属します。リレーションシップ内の以前のオブジェクトは、現在のオブジェクトに関連付けられなくなります。

この問題につながった可能性のある 3 つのシナリオがあります。

  1. 揮発性リストを保持する必要があります - このデータは決して保存されませんが、一時的に使用されます。クラスに通常の属性を作成する必要があります。

    class Computer(models.Model):
        #normal database fields here
    
        def __init__(self, *args, **kwargs):
            super(Computer, self).__init__(*args, **kwargs)
            #ENSURE this attribute name does not collide with any field
            #I'm assuming the Many manager name is projects.
            self.my_projects = []
    
  2. まったく同じ関係を別の表現で表現する必要があります。このように、奇妙な .all() を呼び出す代わりに、オブジェクトに快適にアクセスする方法が必要です[k.foo for k in mycomputer.my_projects]。次のようなプロパティを作成する必要があります。

    class Computer(models.Model):
        #Normal database fields here
        #I'm assuming the Many manager name is projects.
    
        @property
        def my_projects(self):
            #remember: my_projects is another name.
            #it CANNOT collide, so I have another
            #name - cannot use projects as name.
            return list(self.projects.all())
    
        @my_projects.setter
        def my_projects(self, value):
            #this only abstracts the name, to match
            #the getter.
            self.projects = value
    
  3. 別のリレーションシップが必要です (揮発性データではないため): モデルに別のリレーションシップを作成し、同じモードを指し、through該当する場合は同じものを使用しますが、別の related_name= を使用します (複数のリレーションシップの少なくとも 1 つに対して related_name を明示的に設定する必要があります)。同じモデルから、同じモデルへの関係)

于 2014-07-28T16:05:01.960 に答える
1

そんなことはできません。最善の策は、単純に別の属性名を使用することです。

my_computer.related_projects = list(my_computer.projects.all())
于 2014-07-28T16:00:27.480 に答える