我正在使用django的post_save信号在保存模型后执行一些语句.
class Mode(models.Model):
name = models.CharField(max_length=5)
mode = models.BooleanField()
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Mode)
def post_save(sender, instance, created, **kwargs):
# do some stuff
pass
Run Code Online (Sandbox Code Playgroud)
现在我想根据mode字段的值是否发生变化来执行语句.
@receiver(post_save, sender=Mode)
def post_save(sender, instance, created, **kwargs):
# if value of `mode` has changed:
# then do this
# else:
# do that
pass
Run Code Online (Sandbox Code Playgroud)
我查看了一些SOF主题和博客,但找不到解决方案.所有这些都试图使用不是我的用例的pre_save方法或表单.django docs中的https://docs.djangoproject.com/es/1.9/ref/signals/#post-save没有提到直接的方法来做到这一点.
下面的链接中的答案看起来很有希望,但我不知道如何使用它.我不确定最新的django版本是否支持它,因为我曾经ipdb调试过这个并且发现该instance变量没有has_changed下面回答中提到的属性.
我想做一个数据非规范化以获得更好的性能,并在Post模型中收到我的博客帖子收到的一些投票:
class Post(models.Model):
""" Blog entry """
author = models.ForeignKey(User)
title = models.CharField(max_length=255)
text = models.TextField()
rating = models.IntegerField(default=0) # here is the sum of votes!
class Vote(models.Model):
""" Vote for blog entry """
post = models.ForeignKey(Post)
voter = models.ForeignKey(User)
value = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)
当然,我需要保持Post.rating实际价值.Nornally我会使用数据库触发器,但现在我决定发出一个post_save信号(减少数据库处理时间):
# vote was saved
@receiver(post_save, sender=Vote)
def update_post_votes(sender, instance, created, **kwargs):
""" Update post rating """
if created:
instance.post.rating += instance.value
instance.post.save()
else:
# if vote was updated, we need to remove …Run Code Online (Sandbox Code Playgroud) 我正在尝试从其状态创建用户的活动流.
楷模:
class Status(models.Model):
body = models.TextField(max_length=200)
image = models.ImageField(blank=True, null=True, upload_to=get_upload_file_name)
privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
user = models.ForeignKey(User)
class Activity(models.Model):
actor = models.ForeignKey(User)
action = models.CharField(max_length=100)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
Run Code Online (Sandbox Code Playgroud)
但是,虽然我创建了一个新状态,但它不会根据post_save信号创建新活动.
信号:
from django.contrib.contenttypes.models import ContentType
from django.db.models.signals import post_save
from status.models import Status
from models import Activity
def create_activity_item(sender, instance, signal, *args, **kwargs):
if kwargs.get('created', True):
ctype = ContentType.objects.get_for_model(instance)
if ctype.name == …Run Code Online (Sandbox Code Playgroud) 有许多关于使用post_save信号递归的Stack Overflow帖子,评论和答案都是压倒性的:"为什么不覆盖save()"或者只是触发的保存created == True.
我相信不使用的好例子save()- 例如,我正在添加一个临时应用程序来处理与Order模型完全分开的订单履行数据.
框架的其余部分幸福地没有意识到实现应用程序,并且使用post_save挂钩从我们的订单模型中隔离所有与履行相关的代码.
如果我们放弃履行服务,我们的核心代码就不得不改变.我们删除了履行应用程序,就是这样.
那么,是否有任何不错的方法来确保post_save信号不会两次触发相同的处理程序?
我有一个像这样的URL模式:
urlpatterns = (
url(r'^$', list_titles, name='list'),
url(r'^(?P<tag>[a-z\-0-9]+?)/$', list_titles, name='filtered-list'),
url(r'^(?P<title>\S+?)/$', show_title, name='title'),
)
Run Code Online (Sandbox Code Playgroud)
在filtered-list与title匹配同样的事情.
如果有事情匹配的可用列表tag中filtered-list,我要list_titles火了.但是,如果没有匹配tag,我想将其重新发送回URL处理器,以便show_title激活.
如果没有匹配的标题,我会在那里提出一个合适的404.
我知道我可以从视图中做到这一点......但是有点臭,不得不将进程硬连接到视图中.我希望通过URL命令来决定首先选择哪些内容以及它的内容.
我有一个Django模型,我想在保存后或刚刚保存后修改对象权限.我尝试了一些解决方案,post_save信号似乎是我想要做的最佳候选者:
class Project(models.Model):
title = models.CharField(max_length=755, default='default')
assigned_to = models.ManyToManyField(
User, default=None, blank=True, null=True
)
created_by = models.ForeignKey(
User,
related_name="%(app_label)s_%(class)s_related"
)
@receiver(post_save, sender=Project)
def assign_project_perms(sender, instance, **kwargs):
print("instance title: "+str(instance.title))
print("instance assigned_to: "+str(instance.assigned_to.all()))
Run Code Online (Sandbox Code Playgroud)
在这种情况下,创建项目时,信号会触发,我会看到title该assigned_to字段的空列表.
保存后如何访问保存的assigned_to数据?
我需要使用模型进行保存但我需要在保存信号之前断开信号的某些接收器.
我的意思是,
我有一个模特:
class MyModel(models.Model):
...
def pre_save_model(sender, instance, **kwargs):
...
pre_save.connect(pre_save_model, sender=MyModel)
Run Code Online (Sandbox Code Playgroud)
在代码中的另一个地方我需要类似的东西:
a = MyModel()
...
disconnect_signals_for_model(a)
a.save()
...
reconnect_signals_for_model(a)
Run Code Online (Sandbox Code Playgroud)
因为在这种情况下我需要保存模型而不执行函数pre_save_model.
我看到我可以覆盖或定义pre_save, save, post_save在保存模型实例时执行我想要的操作.
在哪种情况下哪一个首选?为什么?
所以我有各种各样的信号和处理程序,它们通过应用程序发送.但是,当我执行测试/进入"测试模式"时,我希望禁用这些处理程序.
在测试模式下是否有一种特定于Django的禁用信号/处理程序的方法?我可以想到一个非常简单的方法(在if TESTING子句中包含处理程序)但我想知道Django中是否有更好的方法?...
我是Django的新手,我无法理解如何使用Django信号.任何人都可以用简单的例子解释" Django信号 "吗?
提前致谢.