如何为DRF Serializer访问/创建正确的Request对象?

时间:2017-08-20 15:46:28

标签: django django-rest-framework django-channels

我已经使用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"序列化程序(没有任何超链接)并使用它们向客户端发送更新。由于超链接不会发生变化,我认为这是正确的方法。

1 个答案:

答案 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对象的字段。