Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add django restframework serializer for activities #38

Open
tbarbugli opened this issue Apr 5, 2016 · 10 comments
Open

add django restframework serializer for activities #38

tbarbugli opened this issue Apr 5, 2016 · 10 comments
Assignees

Comments

@tbarbugli
Copy link
Member

right now serializing enriched data is very complex and requires lot of knowledge of how DRF works (and probably some smart tricks to support nested data / dynamic model serialization).

We should write a basic serializer class to make this easier and write a few example for aggregated/notification and simple activity serialization.

eg.

"is_seen": false,
"is_read": false,
"group": "19931_2016-04-04",
"created_at": "2016-04-04T08:53:42.601",
"updated_at": "2016-04-04T11:33:26.140",
"id": "0bc8c85a-fa59-11e5-8080-800005683205",
"verb": "message",
"activities": [
    {
    "origin": null,
    "verb": "message",
    "time": "2016-04-04T11:33:26.140",
    "id": "0bc8c85a-fa59-11e5-8080-800005683205",
    "foreign_id": "chat.Message:6",
    "target": null,
    "to": [
    "notification:1"
    ],
"actor": "auth.User:1",
"object": "chat.Message:6"
}
@RubenSchmidt
Copy link

I solved it by doing the following:

property tag that returns the serializer class

@property
def activity_object_serializer_class(self):
    from .serializers import FooSerializer
    return FooSerializer

Then used this to serialize the enriched activities. Supports nesting.

@staticmethod
def get_serialized_object_or_str(obj):
        if hasattr(obj, 'activity_object_serializer_class'):
            obj = obj.activity_object_serializer_class(obj).data
        else:
            obj = str(obj)  # Could also raise exception here
        return obj

def serialize_activities(self, activities):
    for activity in activities:
        for a in activity['activities']:
            a['object'] = self.get_serialized_object_or_str(a['object'])
            # The actor is always a auth.User in our case
            a['actor'] = UserSerializer(a['actor']).data
    return activities

Don't know if you can use any of this but i thought i should post it anyway.

Thank you for a great service!

@X17
Copy link

X17 commented Apr 24, 2016

@RubenSchmidt Hey does it work for aggregated feed?

@ghost
Copy link

ghost commented Apr 27, 2016

I'd be very interested in any developments with this enhancement. I've already built out my rest API with DRF and was having a hard time integrating it with stream. Looking forward to any updates! Thanks!

@RubenSchmidt
Copy link

@X17 I am currently only using it for aggregated feed. I am actually not sure if it works properly with the other feeds.

@murdav
Copy link

murdav commented Feb 24, 2017

Is there any news on this issue?

@dwightgunning dwightgunning self-assigned this Sep 20, 2017
@aarcro
Copy link
Contributor

aarcro commented Sep 28, 2017

Take a look at my PR: #67

@morenoh149
Copy link

bumping this. I'm currently trying to power inapp notifications with getstream and django-rest-framework. Any example of this would be very appreciated. Also if I can help in anyway please let me know!

@pterk
Copy link
Contributor

pterk commented Jun 2, 2019

Sorry, never got round to finishing this up but I did some experiments, maybe it will help?:

https://github.com/pterk/django_twitter/blob/master/stream_twitter/serializers.py
https://github.com/pterk/django_twitter/blob/master/stream_twitter/views.py#L141

@morenoh149
Copy link

I've made an so question and minimal drf api to try to solve this https://stackoverflow.com/questions/56435643/django-rest-framework-getstream-notifications

https://github.com/morenoh149/django-rest-framework-getstream

if anyone has ideas please let me know @pterk @aarcro @RubenSchmidt @tbarbugli

@ghost
Copy link

ghost commented Jul 13, 2019

I solved it by doing the following:

property tag that returns the serializer class

@property
def activity_object_serializer_class(self):
    from .serializers import FooSerializer
    return FooSerializer

Then used this to serialize the enriched activities. Supports nesting.

@staticmethod
def get_serialized_object_or_str(obj):
        if hasattr(obj, 'activity_object_serializer_class'):
            obj = obj.activity_object_serializer_class(obj).data
        else:
            obj = str(obj)  # Could also raise exception here
        return obj

def serialize_activities(self, activities):
    for activity in activities:
        for a in activity['activities']:
            a['object'] = self.get_serialized_object_or_str(a['object'])
            # The actor is always a auth.User in our case
            a['actor'] = UserSerializer(a['actor']).data
    return activities

Don't know if you can use any of this but i thought i should post it anyway.

Thank you for a great service!

Your code helped me get started but I was on course to dig into flat feeds. I think how stream's code is built it works differently for flat versus aggregated. Specifically it seems in terms of how I think for aggregated it gives you "activities" whereas for flat feeds I just see EnrichedActivity with an activity_data member variable. Feel free to point out if that's not right. Wouldn't be surprised at all if you had to change your code if you still use stream since that was 2016.

I tried looking through:

https://github.com/morenoh149/django-rest-framework-getstream/blob/0446e410b1a9f440f96989d3c98529e4316e1367/snippets/serializers.py

For if they had given us a way to access the activity data directly to be able to serialize it and I was unable to identify if an accessor had been provided in stream_django. I don't like it but I ended up having to access the member variable directly with the activity data. Even though Tom said he thought we would have issues with DRF I know exactly what I still want to do there but the issue is getting the right data out of stream's classes.

I had their EnrichedActivity(collections.MutableMapping) object in the list returned by:

enriched_activities = enricher.enrich_activities(activities)

and did:

for activity in activities:
       activity = activity.activity_data

and pulled the data back out that I wanted to serialize. If they could dig through a better solution for us for flat feeds that would be ideal. Or just resolve it in general. I'd rather not leave it the way it is. I tried using the __get__ methods but I think those are for specific keys and not entire activity items. Would need a method in stream_django that returns the activity item inside EnrichedActivity. Feel that could be the best bet so I can build my result list and serialize what I want but could need more discussion. @tbarbugli @pterk

PS. I don't want to be forced to use something like:

class ActivitySerializer(serializers.Serializer):
    id = serializers.UUIDField()
    foreign_id = serializers.CharField()
    verb = serializers.CharField()
    time = serializers.DateTimeField()

as the way that I have to serialize my objects. I should be able to have full control on how to serialize my objects irrelevant to how stream has "activities". If I want to add other layers to my serialization steps it should be extendable and allowed via stream. Right now I'm taking fields out of the activity data itself and choosing to return serialized data in the fashion I desire. Maybe I'm alone here but we'll see if others agree. Certainly seems how you build good code, especially in the Django world: loose coupling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants