我已经使用DRF创建了一个REST API,并且运行良好。前端是一个简单的页面,允许查看和更新数据。现在,我正在尝试使用带有django-channels
的WebSockets为站点添加更多交互性。 Channels系统使用起来非常简单,也很好用。
然而,我现在面临的问题是试图将所有动作组合在一起。我的想法是初始页面刷新来自REST API,任何后续更新将在每次更新后自动通过WebSocket(在post_save
信号的帮助下)。我的所有模型都有很好的DRF序列化程序,但是如果没有Request对象(例如HyperLinkedIdentityField
)则不能正常工作:
AssertionError: `HyperlinkedIdentityField` requires the request in the serializer context. Add `context={'request': request}` when instantiating the serializer.
所以我的问题是,在尝试在信号处理程序中序列化模型时,我如何以某种方式创建/伪造Serializers所需的正确Request对象?
修改
我越想到这一点,就越明显这不是正确的方法。无法为序列化器创建单个通用Request
对象,因为触发它们的模型更新可以来自任何源。因此,即使尝试创建一个也没有意义。我想我必须分开" base"序列化程序(没有任何超链接)并使用它们向客户端发送更新。由于超链接不会发生变化,我认为这是正确的方法。
答案 0 :(得分:1)
如果有人可能感兴趣,这就是我解决问题的方法。代码的主要部分如下。
首先是一个简单的模型( myapp / models.py ):
from django.db import models
class MyModel(models.Model):
name = models.TextField()
然后是序列化程序( myapp / serializers.py ):
from rest_framework import serializers
MyModelSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = MyModel
fields = ('url', 'id', 'name')
extra_kwargs = {'url': {'view_name': 'mymodel-detail'}}
MyModelBaseSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('id', 'name')
视图( myapp / views.py ):
from rest_framework import viewsets
from myapp.models import MyModel
from myapp.serializers import MyModelSerializer
class MyModelViewSet(viewsets.ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
最后是频道消息使用者( myapp / consumers.py ):
import json
from django.db.models.signals import pre_save
from django.dispatch import receiver
from channels import Group
from myapp.models import MyModel
from myapp.serializers import MyModelBaseSerializer
def ws_add(message):
message.reply_channel.send({"accept": True})
Group("mymodel").add(message.reply_channel)
def ws_disconnect(message):
Group("mymodel").discard(message.reply_channel)
@receiver(post_save, sender=MyModel)
def mymodel_handler(sender, instance, **kwargs):
Group("mymodel").send({
"text": json.dumps({
"model": "mymodel",
"data": MyModelBaseSerializer(instance).data
})
})
我省略了 urls.py 和 routing.py 等内容,但这些与问题无关。可以看出,常规视图使用包含URL的普通MyModelSerializer
,然后更新处理程序MyModelBaseSerializer
只包含不依赖于任何Request
对象的字段。