0

views.py我有:

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

计算机对象有一个名为项目的字段,它是一个ManyRelatedManager.

打电话

my_projects = my_computer.projects.all()

将值设置my_projects为三个项目对象的列表。

我想要实现的是将 的值设置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时,只有指定的对象将属于关系 - 关系中的先前对象将不再与当前对象相关。

您可能遇到的三种情况会导致您遇到此问题:

  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=(您必须为多个中的至少一个显式设置related_name与同一模型的关系,来自同一模型)

于 2014-07-28T16:05:01.960 回答
1

你不能那样做。您最好的选择是简单地使用另一个属性名称。

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