我搜索了这个问题的简单答案但却找不到任何答案 This question有些看起来像,但不会退出,所以就在这里。
假设我的Django模型中有自定义更新方法。
class People(models.Model):
identifier = models.CharField(max_length=255, primary_key = True)
name = models.CharField(max_length=255)
house = model.ForeignKey(House)
salary = model.IntegerField()
def my_fancy_update(self, **kwargs):
# Here I want to do my update
pass
我想要做的是使用kwargs
来更新我的模型
现在我使用以下内容:
def my_fancy_update(self, **kwargs):
self.name = kwargs.get('name')
self.house = kwargs.get('house')
self.salary = kwargs.get('salary')
self.save()
这看起来像我真正想做的事情:
def my_fancy_update(self, **kwargs):
self.update(**kwargs)
self.update
不起作用会引发错误:
AttributeError: 'People' object has no attribute 'update'
由于使用self.objects.update
时无法访问经理,因此无法self
。
我现在的问题是,如果这是可能的,以及如何在Django中完成。
它节省了我在实际模型中列出每个属性的大量时间。
答案 0 :(得分:3)
请注意您当前的解决方案:
def my_fancy_update(self, **kwargs):
self.name = kwargs.get('name')
self.house = kwargs.get('house')
self.salary = kwargs.get('salary')
self.save()
非常脆弱,因为它可以将任何名称,住宅和工资设置为None
。
第一个干净的解决方案是使用for循环和设置:
def my_fancy_update(self, **kwargs):
for name, value in kwargs.items():
setattr(self, name, value)
self.save()
但这仍然很脆弱,因为它没有检查传递的名称实际上是模型字段名称。更安全的实现将使用self._meta.get_fields()
来检查:
def my_fancy_update(self, **kwargs):
fieldnames = set(f.name for f in self._meta.get_fields())
for name, value in kwargs.items():
if name not in fieldnames:
raise ValueError("%s is not a field of %s" % (name, type(self).__name__))
setattr(self, name, value)
self.save()
最后,如果没有更新任何内容,您可能希望避免调用save()
,并且只提交实际更新的内容:
def my_fancy_update(self, **kwargs):
if not kwargs:
return
fieldnames = set(f.name for f in self._meta.get_fields())
updated = []
for name, value in kwargs.items():
if name not in fieldnames:
raise ValueError("%s is not a field of %s" % (name, type(self).__name__))
setattr(self, name, value)
updated.append(name)
self.save(update_fields=updated)
答案 1 :(得分:2)
我们可以遍历属性并更新值,然后调用.save()
函数:
def my_fancy_update(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
self.save()
然而,这将手动设置属性,因此可能会附加一些信号,触发器等,以更新和清除值。
setattr(..)
是一个Python函数,setattr(x, 'y', z)
等同于x.y = z
(请注意,我们将'y'
作为setattr(..)
中的字符串传递。
也无法更新related_field__attribute
等属性