我有以下型号:
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)
当我操作这些东西时,在布尔值更新的视图中,第一种方法不起作用,但第二种方法有效。使用第一个和第二个之间有什么区别,什么时候应该使用它们?
谢谢!
答案 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])
“不工作”可能不依赖于您设置值的方式,您确定之后保存了更改吗?