Django - 如何将模型字段重置为默认值?

13

如何以最简洁高效的方式将特定模型实例的所有字段重置为其默认值?


我认为我可能误解了你的问题——你想将每个字段设置为模型上每个字段对象编码的“默认”值,还是将每个字段设置回修改字段值之前的值? - Matthew J Morrison
1
@Matthew - 前者。如果我想要后者,我会使用django-reversion。 - Jonathan Livni
8个回答

8
我曾经用这种方式来做。我没有想到更好的方法。
from django.db.models.fields import NOT_PROVIDED

for f in instance._meta.fields:
    if f.default <> NOT_PROVIDED:
        setattr(instance, f.name, f.default)

# treatment of None values, in your words, to handle fields not marked with null=True
...
...
# treatment ends

instance.save()

注意:在我的情况下,所有字段都有默认值。
希望这对你有所帮助。愉快编码!

4
def reset( self, fields=[], exclude=[] ):

    fields = fields or filter( lambda x: x.name in fields, self._meta.fields )
    exclude.append( 'id' )        

    for f in filter( lambda x: x.name not in exclude, fields ):
        if getattr( f, 'auto_now_add', False ):
            continue

        if f.blank or f.has_default():
            setattr( self, f.name, f.get_default() )

这段代码存在一个错误,使用[]作为默认参数。您一遍又一遍地修改同一个列表,向其中添加'id'。https://docs.python-guide.org/writing/gotchas/ - rrauenza

2

这种方法主要适用于将单个值重置为默认值,但可以进行适应。它会重置所有我的Event对象的rego_update属性。

Event.objects.all().update(rego_update=Event().rego_update)

另外,如果要单独应用它(即触发自定义save方法):

default = Event().rego_update  # Hack to fetch the default
for event in Event.objects.all():
    event.rego_update = default
    event.save()

为了将其适应于重置单个实例的所有值,您可以手动使用默认值重置每个值。
或者,您可以像其他答案中一样循环遍历属性,但这将会导致没有默认值(或无法编辑)的字段出现问题。

你的解决方案显然比我的更啰嗦!聪明;-) - Julien Kieffer

1

None 分配给字段,并保存。


2
这种方式只在某些情况下才适用,不是吗?例如,对于没有标记为空(blank=True)或允许为null(null=True)的字段,它是否适用? - Jonathan Livni
1
数据库中插入或更新 NULL 值将被更改为字段的默认值。 - Ignacio Vazquez-Abrams
@Jonathan 我非常确定你是对的。如果它们只成为默认值,Django为什么会有“null = True”字段呢? - Mark

0

通过检查.null字段属性,将不可为空的所有字段都分配为None:

for name, value in {f.name: None for f in self._meta.fields if f.null}:
    setattr(instance, name, value)
instance.save()

0

你可以使用 self.your_field = self.__class__._meta.get_field('your_field').default

请注意,根据你的 Django 版本,get_field 可能会有其他名称,因此请将其包装在 try/except 中。


0

在您对该实例进行更改之后,但在“保存”之前,我假设?我认为您可能需要从数据库中重新检索它... 我不认为Django模型实例会保留已对实例进行的更改的“历史记录”。


0
另一个解决方案是创建一个空的模型实例,然后使用它来更新当前的实例,就像这样:
def reset(self):
    new_instance = type(self)()
    self.__dict__.update(new_instance.__dict__)

或者如果你想保留模型 ID:

def reset(self):
    new_instance = type(self)(id=self.id)
    self.__dict__.update(new_instance.__dict__)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接