Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django-使用kwargs更新Django模型对象内的字段_Python_Django_Django Models - Fatal编程技术网

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
有什么问题?May
update\u或\u create
help?@AmaroVita不,不是真的,因为
update\u或\u create
也不是模型本身的方法,而是模型的管理者的方法。而且
self
也无法访问管理者,所以这不是work@Nebulosar,可以是,
self.\uuuuuu类\uuuuuuuu.o对象。更新或创建()
那么?self.update有什么问题吗?May
update\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
方法中的未知字段应该不会引起任何问题。但再一次,这取决于你…谢谢你的回答。我不是