gpt4 book ai didi

django - 如何在保存过程中排除 django 模型字段?

转载 作者:行者123 更新时间:2023-12-02 20:57:06 24 4
gpt4 key购买 nike

我有一个相当复杂的 Django 模型,其中包含一些仅应在某些情况下保存的字段。举个简单的例子,

from django.db import models

class MyModel(models.Model):
name = models.CharField(max_length=200)
counter = models.IntegerField(default=0)

def increment_counter(self):
self.counter = models.F('counter') + 1
self.save(update_fields=['counter'])

这里我使用F expressions在增加计数器时避免竞争条件。我通常不想将 counter 的值保存在 increment_counter 函数之外,因为这可能会撤消从另一个线程或进程调用的增量。

所以问题是,在模型的保存功能中默认排除某些字段的最佳方法是什么?我尝试过以下方法

def save(self, **kwargs):
if update_fields not in kwargs:
update_fields = set(self._meta.get_all_field_names())
update_fields.difference_update({
'counter',
})
kwargs['update_fields'] = tuple(update_fields)
super().save(**kwargs)

但这会导致ValueError:以下字段在此模型中不存在或者是m2m字段:id。我当然可以在差异更新中添加 id 和任何 m2m 字段,但这开始看起来像是一团难以维护的困惑,特别是当其他模型开始引用这个模型时,这将在需要从 update_fields 中排除的 self._meta.get_all_field_names()

就其值(value)而言,我主要需要此功能来与 django 管理站点交互;代码中的所有其他位置都可以相对轻松地使用正确的 update_fields 调用 model_obj.save()

最佳答案

我最终使用了以下内容:

from django.db import models

class MyModel(models.Model):
name = models.CharField(max_length=200)
counter = models.IntegerField(default=0)

default_save_fields = None

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.default_save_fields is None:
# This block should only get called for the first object loaded
default_save_fields = {
f.name for f in self._meta.get_fields()
if f.concrete and not f.many_to_many and not f.auto_created
}
default_save_fields.difference_update({
'counter',
})
self.__class__.default_save_fields = tuple(default_save_fields)

def increment_counter(self):
self.counter = models.F('counter') + 1
self.save(update_fields=['counter'])

def save(self, **kwargs):
if self.id is not None and 'update_fields' not in kwargs:
# If self.id is None (meaning the object has yet to be saved)
# then do a normal update with all fields.
# Otherwise, make sure `update_fields` is in kwargs.
kwargs['update_fields'] = self.default_save_fields
super().save(**kwargs)

这似乎适用于我的更复杂的模型,该模型在其他模型中作为外键引用,尽管可能存在一些它未涵盖的边缘情况。

关于django - 如何在保存过程中排除 django 模型字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33225000/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com