djangochannelsrestframework
djangochannelsrestframework copied to clipboard
Current user in model observer
Is your feature request related to a problem? Please describe. Current docs indicate the following case
''' If you want the data serializeded instead of pk '''
@model_change.serializer
def model_serialize(self, instance, action, **kwargs):
return TestSerializer(instance).data
I have a serializer that requires self.context['scope'].get('user')
. Used to return "You" if its self.context['scope'].get('user')
else the User instance
when passing instance to TestSerializer in mode_serialize, getting key error on "scope" I can do
return TestSerializer(instance, context={'request': request}).data
but I have no access to request to pass to the serializer.
How do I access the request on a model observer?
What is your goal in changing the Serializer
? is this to change the values sent to the client or to change values sent to other consumers so that you can do permission checks without hitting the db?
With respect to building a fake
HTTP request object there is an example here in the code base:
https://github.com/hishnash/djangochannelsrestframework/blob/master/djangochannelsrestframework/consumers.py#L220
if this method works for creating your context i will look into how i can provide an api on the consumer to build it.
I am not changing the serializer, my serializer needs the current user. I just need to pass the current user model_observer, so the serializer can handle serialization
ok. are you using ObserverModelInstanceMixin
or a custom @model_observer
?
Here's my code
class NotificationsConsumer(ListModelMixin, RetrieveModelMixin, GenericAsyncAPIConsumer):
serializer_class = NotificationSerializer
def get_queryset(self, **kwargs):
qs = get_user_notifications(model=Notification, user=self.scope["user"])
return qs
async def accept(self, **kwargs):
await super().accept()
await self.model_change.subscribe()
@model_observer(Notification)
async def model_change(self, message, **kwargs):
await self.send_json(message)
# @model_change.serializer
# def model_serialize(self, instance, action, **kwargs):
# request = {}
# request['scope'] = self.scope
# return NotificationSerializer(instance, context={'request': request}).data
Btw, I would be glad to help implement pagination and any extra context to serializer on Consumer
Btw, I would be glad to help implement pagination and any extra context to serializer on Consumer
That would be very welcome :)
for the context on serializer if you look at https://github.com/hishnash/djangochannelsrestframework/blob/master/djangochannelsrestframework/consumers.py#L220 maybe extract this logic that builds the fake HttpRequest
into a computed property on AsyncAPIConsumer
then in GenericAsyncAPIConsumer
you can use this property in get_serializer_context
https://github.com/hishnash/djangochannelsrestframework/blob/29fa48bda71c64aa32ea4f5c3c270f062fb882a4/djangochannelsrestframework/generics.py#L115
pagination
Is a more complex task.. i see there are 2 different features that fall under that title:
- pagination were the client requests page X (like DRF)
- pagination streaming were you request a list of data but rather than getting it all in one massive chunk it is sent to you in smaller sub-chunks (the aim here is so the client does not need to wait for the server to serialise all the data before some of it arrives)
Which of these did you have in mind for your use case?
I have made my socket to output a short list of recent results, and on model change, I just request the list anew! And there is a separate page of notifications simply using Django ListView with pagination. This way I also don't need the extra context on the model observer. Seems I found a workaround. However, initially I wanted it to send the results paginated, and than lazy-load next pages, which fall under option 1 as I can understand.
Hi, how to user get_serializer_context to pass extra context to serializer?