为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕的地10843 2023-01-04 16:35:47

尝试使用信号通过 websockets 发送使用 .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 回答

?
猛跑小猪

TA贡献1603条经验 获得超8个赞

前奏:处理通道水合作用

要了解上次修改的内容,您需要一个上次修改字段。这是一个非常著名的模式,Django 使用auto_now=TrueDateTimeFields 的参数来帮助它。这些字段不可编辑,并尽可能使用数据库触发器来获得结果(这就是它们不可编辑的原因)。


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


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

现在获取最后修改的记录并用最后修改的通道填充通道是微不足道的,无论是否发生保存:


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')

信号交易

但是,如果我们使用后保存信号,我们已经在“实例”参数中有了刚刚保存的对象。为了方便的转成json,我们可以使用model_to_dict和DjangoJSONEncoder来处理大部分问题:


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},

    )

Model_to_dict 会将模型转换为字典,并且可以使用fields=(explicit include) 或exclude=(explicit exclude) 进行限制。DjangoJSONEncoder 处理时间数据,json 的默认编码器不支持。


查看完整回答
反对 回复 2023-01-04
?
拉莫斯之舞

TA贡献1544条经验 获得超10个赞

我想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)


查看完整回答
反对 回复 2023-01-04

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信