Python Django-使用kwargs更新Django模型对象内的字段
我搜索了这个问题的简单答案,但没有找到任何答案。Python Django-使用kwargs更新Django模型对象内的字段,python,django,django-models,Python,Django,Django Models,我搜索了这个问题的简单答案,但没有找到任何答案。 看起来有点像,但不是一样,所以在这里 假设我在Django模型中有一个自定义更新方法 class People(models.Model): identifier = models.CharField(max_length=255, primary_key = True) name = models.CharField(max_length=255) house = model.ForeignKey(House)
看起来有点像,但不是一样,所以在这里 假设我在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:“人员”对象没有属性“更新”
另外,由于使用self
时无法访问管理器,因此无法执行self.objects.update
我现在的问题是,这是否可能,以及如何在Django做到这一点。列出实际模型中的每个属性可以节省我很多时间 我们可以迭代属性并更新值,然后调用
.save()
函数:
def my_fancy_update(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
self.save()
def my_fancy_update(self,**kwargs):
对于k,v在kwargs.items()中:
setattr(自、k、v)
self.save()
但是,这将手动设置属性,因此可能会附加一些信号、触发器等来更新和清除值
setattr(…)
是一个Python函数,因此setattr(x,'y',z)
相当于x.y=z
(请注意,我们在setattr(…)
中以字符串形式传递'y'
)
也不可能更新属性,如
相关的\u字段\u属性
等。我们可以迭代属性并更新值,然后调用.save()
函数:
def my_fancy_update(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
self.save()
def my_fancy_update(self,**kwargs):
对于k,v在kwargs.items()中:
setattr(自、k、v)
self.save()
但是,这将手动设置属性,因此可能会附加一些信号、触发器等来更新和清除值
setattr(…)
是一个Python函数,因此setattr(x,'y',z)
相当于x.y=z
(请注意,我们在setattr(…)
中以字符串形式传递'y'
)
也不可能更新属性,如
相关的\u字段\u属性
等。请注意,您当前的解决方案:
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循环和settattr:
def my_fancy_update(self, **kwargs):
for name, value in kwargs.items():
setattr(self, name, value)
self.save()
但这仍然很脆弱,因为它不会检查传递的名称是否确实是模型字段名称。更安全的实现方法是使用self.\u meta.get\u 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)
请注意,您当前的解决方案:
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循环和settattr:
def my_fancy_update(self, **kwargs):
for name, value in kwargs.items():
setattr(self, name, value)
self.save()
但这仍然很脆弱,因为它不会检查传递的名称是否确实是模型字段名称。更安全的实现方法是使用self.\u meta.get\u 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)
self.update
有什么问题?Mayupdate\u或\u create
help?@AmaroVita不,不是真的,因为update\u或\u create
也不是模型本身的方法,而是模型的管理者的方法。而且self
也无法访问管理者,所以这不是work@Nebulosar,可以是,self.\uuuuuu类\uuuuuuuu.o对象。更新或创建()
那么?self.update有什么问题吗?Mayupdate\u或\u create
help?@AmaroVita不,不是真的,因为update\u或\u create
也不是模型本身的方法,而是模型的管理者的方法。而且self
也无法访问管理者,所以这不是work@Nebulosar,可以是,self、 类对象。更新或创建()
然后呢?嗨,威廉,谢谢你回答我的问题,我已经看到了你更多关于我问题的答案,我对此表示感谢!谢谢你。它小而简单,正是我所需要的。事实上,威廉的名字无处不在:D一如既往的简短而伟大的答案!谢谢威廉,谢谢你回答我的问题,我在我的问题上看到了你更多的答案ons,我很感激!谢谢。它很小很简单,正是我所需要的。事实上,威廉的名字到处都是:D一如既往的简短而伟大的答案!感谢你的回答。我不确定你是否应该通过执行ValueError
来强迫用户只通过有效的kwargs,但这不是真正的问题。再次感谢!@Nebulo就我而言,sar(作为开发人员),我宁愿使用这个ValueError
,这样我就可以知道什么时候我输入了一个字段名,或者在模式更改后某些代码没有正确更新,但是YMMV…我理解你的论点,市场可能确实会有所不同,所以我想解释我在这种情况下的观点:比如说,在自动导入大型XML文件时,你只需要ant要导入有效的内容,数据本身是不相关的,提供数据的一方负责确保这是正确的。导入时,我不想引起错误。在这种情况下,最好的做法是记录错误。因此,当某些字段不正确时,您也可以记录它,以便查看发生了什么g错误,仍然更新字段或类似内容。@Nebulosar用户数据(无论来自何处)无论如何,在点击模型之前必须经过消毒/验证/最终预处理,因此如果调用方完成了工作,那么拒绝update
方法中的未知字段应该不会引起任何问题。但再一次,这取决于你…谢谢你的回答。我不是