Django信号-通过django管理员更新模型时,kwargs ['update_fields']始终为None [英] Django signals - kwargs['update_fields'] is always None on model update via django admin
问题描述
我的django应用程序内部有一个信号,我想检查模型中的某个字段是否已更新,因此我可以继续进行操作。
I have a signal inside my django app where I would like to check if a certain field in my model has been updated, so I can then proceed and do something.
我的模型看起来像这样...
My model looks like this...
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.PositiveIntegerField()
tax_rate = models.PositiveIntegerField()
display_price = models.PositiveInteger()
inputed_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL)
我的信号看起来像这样...
My signal looks like this...
@receiver(post_save, sender=Product)
def update_model(sender, **kwargs):
instance = kwargs['instance']
if 'tax_rate' in kwargs['update_fields']:
# do something
这将返回错误 None
不可迭代。我已经阅读了有关 update_fields
的django信号文档,上面写着传递给Model.save()的要更新的字段集;如果没有,我没有提到update_fields传递给save()。
This returns the error None
is not an iterable. I have read the django signal documentation regarding the update_fields
and it says The set of fields to update as passed to Model.save(), or None if update_fields wasn’t passed to save().
我应该提到我在django管理员内部工作,所以我希望会发生,我可以在django admin中创建我的产品模型的实例,然后再更新tax_rate或price的值时,可以检查它们并相应地更新 list_price
。但是, kwargs ['update_fields']
始终返回None。
我怎么了?还是我可以在django管理员中实现该结果的其他方法?
I should mention that I am working inside django admin here so what I hoped would happen is, I could create an instance of my Product model in django admin and then later if the value of tax_rate or price were updated, I could check for those and update the list_price
accordingly. However, kwargs['update_fields']
always returns None.
What am I getting wrong? Or is there some other way I could achieve that result inside django admin?
更新的部分
现在,假设我在产品模型中引入了一个名为 inputed_by
的字段,该字段指向用户模型,我希望在首次保存模型时填充该字段。然后,另一个字段 updated_by
存储上次更新模型的用户。同时,我想检查 tax_rate
或 price
中的一个或两个是否都已更新。
Now, say I introduce a field called inputed_by
in my product model, that points to the user model and I want that field populated when the model is first saved. Then another field updated_by
that stores the user who last updated the model. At the same time I wish to check whether either or both the tax_rate
or price
has been updated.
在模型管理员内部,我有以下方法...
Inside my model admin I have the following method...
def save_model(self, request, obj, form, change):
update_fields = []
if not obj.pk:
obj.inputed_by = request.user
elif change:
obj.updated_by = request.user
if form.initial['tax_rate'] != form.cleaned_data['tax_rate']:
update_fields.append('tax_rate')
if form.initial['price'] != form.cleaned_data['price']:
update_fields.append('price')
obj.save(update_fields=update_fields)
super().save_model(request, obj, form, change)
我的信号现在看起来像这样...
My signal now looks like this...
@receiver(post_save, sender=Product, dispatch_uid="update_display_price")
def update_display_price(sender, **kwargs):
created = kwargs['created']
instance = kwargs['instance']
updated = kwargs['update_fields']
checklist = ['tax_rate', 'price']
# Prints out the frozenset containing the updated fields and then below that `The update_fields is None`
print(f'The update_fields is {updated}')
if created:
instance.display_price = instance.price+instance.tax_rate
instance.save()
elif set(checklist).issubset(updated):
instance.display_price = instance.price+instance.tax_rate
instance.save()
我得到了错误'NoneType'对象是不可迭代的
该错误似乎来自 set(checklist)行。 issubset(已更新)
。我尝试过专门在python shell内运行该行,它会产生所需的结果。这次出了什么事?
I get the error 'NoneType' object is not iterable
The error seems to come from the line set(checklist).issubset(updated)
. I've tried running that line specifically inside the python shell and it yields the desired results. What's wrong this time?
推荐答案
应将字段集传递给 Model.save()
使其在 update_fields
中可用。
The set of fields should be passed to Model.save()
to make them available in update_fields
.
像这样
model.save(update_fields=['tax_rate'])
如果您是通过django管理员创建的,并且总是无
,则表示 update_fields
尚未传递给模型的 save
方法。因此,它将始终为无
。
If you are creating something from django admin and getting always None
it means that update_fields
has not been passed to model's save
method. And because of that it will always be None
.
如果您选中 ModelAdmin
类和 save_model
方法,您会发现调用是在没有 update_fields
关键字参数的情况下发生的。
If you check ModelAdmin
class and save_model
method you'll see that call happens without update_fields
keyword argument.
如果您自己编写 save_model
。
以下代码将解决您的问题:
The code below will solve your problem:
class ProductAdmin(admin.ModelAdmin):
...
def save_model(self, request, obj, form, change):
update_fields = []
# True if something changed in model
# Note that change is False at the very first time
if change:
if form.initial['tax_rate'] != form.cleaned_data['tax_rate']:
update_fields.append('tax_rate')
obj.save(update_fields=update_fields)
现在您可以测试成员资格了在 update_model
中。
Now you'll be able to test memberships in update_model
.
这篇关于Django信号-通过django管理员更新模型时,kwargs ['update_fields']始终为None的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!