python / django中setattr和对象操作之间的区别

时间:2012-10-09 13:48:20

标签: python django django-models setattribute setattr

我有以下型号:

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

第二

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

当我操作这些东西时,在布尔值更新的视图中,第一种方法不起作用,但第二种方法有效。使用第一个和第二个之间有什么区别,什么时候应该使用它们?

谢谢!

2 个答案:

答案 0 :(得分:34)

这更像是一个Python问题。

Python是非常动态的语言。您可以提前编写事物(类),或者Python允许您在运行时完全动态地创建类。考虑以下简单向量类的示例。您可以提前创建/编写类,如:

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

或者您可以通过执行以下操作动态创建类:

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

方法之间的主要区别在于,您可以提前知道类属性,而对于您可以想象的第二种方法,您可以以编程方式创建fields字典,因此您可以完全动态创建类(ES)。

因此,当您提前知道类的属性时,可以使用对象表示法设置类属性:

instance.attribute = value

请记住,这相当于:

instance.__setattr__(attribute, value)

但是,有些情况下您不知道需要提前操作的类属性。您可以在此处使用__setattr__功能。但是不推荐练习。所以建议使用Python的内置方法setattr,它在内部调用__setattr__方法:

setattr(instance, attribute, value)

使用这种方法,你可以提前设置你不知道的属性,或者甚至可以循环一些dict并从dict设置值:

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

不确定为什么常规符号不起作用。它可能与您用于设置属性的方法无关。

答案 1 :(得分:9)

如果您事先知道对象属性,则可能应该使用第一种方法。只需直接指定属性值即可。

当您需要为属性动态分配值时,第二个非常有用。也许用户可以更改许多不同属性的值,而你不知道哪一个会有一个值,你可以动态添加值

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])

“不工作”可能不依赖于您设置值的方式,您确定之后保存了更改吗?