Django 和模型中的信号 post_save
Signal post_save in Django and models
我有信号功能:
@receiver(post_save, sender=Task)
def my_handler():
executor = User.objects.filter(user_type='Executer')
executor.balance += Task.money
executor.save()
我的功能应该在添加任务后向执行者添加资金。但它给出了这样的错误:
Internal Server Error: /api/v1/tasks/
Traceback (most recent call last):
...
File "/home/k/pro/freelance-django/free/lib/python3.5/site-packages/django/db/models/fields/__init__.py", line 1853, in get_prep_value
return int(value)
ValueError: invalid literal for int() with base 10: 'Executer'
[20/Sep/2017 14:00:30] "POST /api/v1/tasks/ HTTP/1.1" 500 188088
用户 class 看起来像:
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
CUSTOMER = 1
EXECUTER = 2
USER_TYPES = (
(CUSTOMER, 'Customer'),
(EXECUTER, 'Executer'),
)
user_type = models.IntegerField(choices=USER_TYPES, default=EXECUTER, verbose_name='Тип пользователя')
balance = models.DecimalField(decimal_places=2, max_digits=7, default=0, verbose_name='Баланс')
def __str__(self):
return self.username
来自 task.models 的任务 class 是:
class Task(models.Model):
title = models.CharField(max_length=255, verbose_name='Заголовок')
description = models.CharField(max_length=255, verbose_name='Описание')
money = models.DecimalField(max_digits=7, decimal_places=2, default=0, verbose_name='Цена')
assignee = models.ForeignKey('users.User', related_name='assignee', null=True, verbose_name='Исполнитель')
created_by = models.ForeignKey('users.User', related_name='created_by', verbose_name='Кем был создан')
我应该如何让它发挥作用?
你没有一个 object 但是 objects 所以你需要对它们进行文字处理或者做 update()
.最好的选择是使用 F 表达式,它具有良好的性能,因为它在 DB:
上执行
from django.db.models import F
@receiver(post_save, sender=Task)
def my_handler(sender, instance, **kwargs):
User.objects.filter(user_type=User.EXECUTER).update(balance=F('balance') + instance.money)
这会更新 user_type 是执行者的所有记录,并在一个查询中更新它们的余额。
你的 user_type
字段是 IntegerField 并且在你的选择中你有字符串值所以你需要将它更改为这样的东西:
class User(AbstractUser):
CUSTOMER = 1
EXECUTER = 2
USER_TYPES = (
(CUSTOMER, 'Customer'),
(EXECUTER, 'Executer'),
)
user_type = models.IntegerField(choices=USER_TYPES, default=EXECUTER, verbose_name='Тип пользователя')
balance = models.DecimalField(decimal_places=2, max_digits=7, default=0, verbose_name='Баланс')
我有信号功能:
@receiver(post_save, sender=Task)
def my_handler():
executor = User.objects.filter(user_type='Executer')
executor.balance += Task.money
executor.save()
我的功能应该在添加任务后向执行者添加资金。但它给出了这样的错误:
Internal Server Error: /api/v1/tasks/
Traceback (most recent call last):
...
File "/home/k/pro/freelance-django/free/lib/python3.5/site-packages/django/db/models/fields/__init__.py", line 1853, in get_prep_value
return int(value)
ValueError: invalid literal for int() with base 10: 'Executer'
[20/Sep/2017 14:00:30] "POST /api/v1/tasks/ HTTP/1.1" 500 188088
用户 class 看起来像:
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
CUSTOMER = 1
EXECUTER = 2
USER_TYPES = (
(CUSTOMER, 'Customer'),
(EXECUTER, 'Executer'),
)
user_type = models.IntegerField(choices=USER_TYPES, default=EXECUTER, verbose_name='Тип пользователя')
balance = models.DecimalField(decimal_places=2, max_digits=7, default=0, verbose_name='Баланс')
def __str__(self):
return self.username
来自 task.models 的任务 class 是:
class Task(models.Model):
title = models.CharField(max_length=255, verbose_name='Заголовок')
description = models.CharField(max_length=255, verbose_name='Описание')
money = models.DecimalField(max_digits=7, decimal_places=2, default=0, verbose_name='Цена')
assignee = models.ForeignKey('users.User', related_name='assignee', null=True, verbose_name='Исполнитель')
created_by = models.ForeignKey('users.User', related_name='created_by', verbose_name='Кем был создан')
我应该如何让它发挥作用?
你没有一个 object 但是 objects 所以你需要对它们进行文字处理或者做 update()
.最好的选择是使用 F 表达式,它具有良好的性能,因为它在 DB:
from django.db.models import F
@receiver(post_save, sender=Task)
def my_handler(sender, instance, **kwargs):
User.objects.filter(user_type=User.EXECUTER).update(balance=F('balance') + instance.money)
这会更新 user_type 是执行者的所有记录,并在一个查询中更新它们的余额。
你的 user_type
字段是 IntegerField 并且在你的选择中你有字符串值所以你需要将它更改为这样的东西:
class User(AbstractUser):
CUSTOMER = 1
EXECUTER = 2
USER_TYPES = (
(CUSTOMER, 'Customer'),
(EXECUTER, 'Executer'),
)
user_type = models.IntegerField(choices=USER_TYPES, default=EXECUTER, verbose_name='Тип пользователя')
balance = models.DecimalField(decimal_places=2, max_digits=7, default=0, verbose_name='Баланс')