Django信号-如何使用post_save发送保存在模型中的内容?

时间:2020-06-09 13:45:41

标签: python django django-models django-channels django-signals

尝试使用信号通过websocket发送使用.save()保存的最后一条记录。我在data中输入什么?

#models.py
from django.db import models
from django.db.models.signals import post_save
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync

class DataModel(models.Model):
    time = models.DateTimeField()
    value = models.FloatField()

    def __str__(self):
        return str(self.time)

def save_post(sender, instance, **kwargs):
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        "echo_group",
        {"type": "on.message", "data": data},
    )

post_save.connect(save_post, sender=DataModel)

我想我可以获取具有最高索引的记录并将其发送,但是想知道是否有更优雅的解决方案。

2 个答案:

答案 0 :(得分:2)

我认为instance.__dict__是您想要的。它将所有模型属性转换为字典键-值对

所以您可以做类似的事情

def save_post(sender, instance, **kwargs):
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        "echo_group",
        {"type": "on.message", "data": instance.__dict__},
    )

已更新

我略过提及instance是刚刚保存并触发post_save信号的实际对象。因此,在给定的问题中,instance类似于instance = DataModel.objects.create(**kwargs)

答案 1 :(得分:2)

前奏:处理通道水合

要知道最后修改的内容,您需要一个最后修改的字段。这是一个非常著名的模式,Django使用 draggable.draggable({ onmove: onMove.bind(this) }) 参数的DateTimeFields来帮助它。这些字段不可编辑,并在可能的情况下使用数据库触发器来获得结果(这就是为什么它们不可编辑的原因)。

如上所述,这很常见,所以我通常使用基本模型:

auto_now=True

现在,不管是否发生保存,获取上次修改的记录并为上一次修改的频道充水都是很简单的:

class AuditableBase(models.Model):
    """
    Base class that adds created_at and last_modified fields for audit purposes.
    """

    created_at = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

信号处理程序

但是,如果使用后保存信号,则在“实例”参数中已经有刚刚保存的对象。要将其轻松转换为json,我们可以使用model_to_dict和DjangoJSONEncoder处理大多数问题:

class DataModel(AuditableBase):
    time = models.DateTimeField()
    value = models.FloatField()

    def __str__(self):
        return str(self.time)

# On channel start:
latest = DataModel.objects.latest('last_modified')

Model_to_dict会将模型转换为字典,并且可以使用from django.forms.models import model_to_dict from django.core.serializers import DjangoJSONEncoder import json def save_post(sender, instance, **kwargs): channel_layer = get_channel_layer() data = model_to_dict(instance) json_data = json.dumps(data, cls=DjangoJSONEncoder) async_to_sync(channel_layer.group_send)( "echo_group", {"type": "on.message", "data": json_data}, ) (显式包含)或fields=(显式排除)进行限制。 DjangoJSONEncoder处理时间数据,而json的默认编码器不支持该数据。