Skip to main content

Hyper Media Channels Rest Framework.

Project description

A Hyper Media style serializer for DjangoChannelsRestFramework.

https://travis-ci.org/hishnash/hypermediachannels.svg?branch=master

API USAGE

This is a collection of serialisers and serialiser fields that creats a hypermidea style like PK

Setting up your consumers

All of your consumers should be mapped through a AsyncJsonWebsocketDemultiplexer.

from channelsmultiplexer import AsyncJsonWebsocketDemultiplexer
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from hypermediachannels.serializers import HyperChannelsApiModelSerializer

class UserSerializer(HyperChannelsApiModelSerializer):
  class Meta:
      model = User
      fields = (
          '@id',
          'username'
      )

class UserConsumer(GenericAsyncAPIConsumer):
    queryset = User.objects.all()
    serializer_class = UserSerializer

class MainDemultiplexer(AsyncJsonWebsocketDemultiplexer):
    applications = {
        'users': UserConsumer,
    }

Then when configuring your Channels Application add the MainDemultiplexer as your main consumer. This way all Websocket connections on that URL will run through the Demultiplexer. See DjangoChannelsRestFramework for more deaitls on how to write consumers.

HyperChannelsApiModelSerializer

This can be used inplace of the DRF ModelSerializer. It will (if you include @id in the fields list) add a self reference to the model being displayed)

eg User model Serialiser might respond like this if its fields are ('@id', 'username', 'profile')

{
   @id: {
     stream: 'user',
     payload: {
       action: 'retrieve',
       pk: 1023
      }
   },
   username: 'bob@example.com',
   profile: {
     stream: 'profile',
     payload: {
       action: 'retrieve',
       pk: 23
     }
   }
}

This will under the hood use HyperlinkedIdentityField to create the @id and profile fields and they will (by default) return these retrieve objects.

Why do we do this.

this means that if we then need to lookup that profile for this user we can just send the msg:

{
  stream: 'profile',
  payload: {
    action: 'retrieve',
    pk: 23
  }
}

Down the websocket and we will get that item, the frontend code does not need to track all of these lockup logic, (consider that some models might have lookup that is not based on pk for example).

If you need to define a different set of lookup params. You can use the kwarg_mappings, stream_name and action_name kwargs to override this.

eg:

class UserSerializer(HyperChannelsApiModelSerializer):
    class Meta:
        model = get_user_model()
        fields = (
            '@id', 'username', 'profile'
        )

        extra_kwargs = {
            'profile': {
                'action_name': 'user_profile',
                'kwarg_mappings': {
                    'user_pk': 'self.pk',
                    'team_pk': 'team.pk'
                }
            },
        }

the kwarg_mappings will set the value in the response user_pk by extracting the pk value on from the User instance.

(pre-appending self to the kwarg_mappings value means it will do the lookup based on the instance parsed to the parent Serializer rather than the instance for this field. In this case a user profile).

so the above would return:

{
   @id: {
     stream: 'user',
     payload: {
       action: 'retrieve',
       pk: 1023
      }
   },
   username: 'bob@example.com',
   profile: {
     stream: 'user_profile',
     payload: {
       action: 'retrieve',
       user_pk: 1023,
       team_pk: 234234
     }
   }
}

You can use . to access nested values eg. profile.team.name.

Alternatively you can create fields as you would in DRF.
class UserSerializer(HyperChannelsApiModelSerializer):
    team = HyperChannelsApiRelationField(
        source='profile.team',
        kwarg_mappings={
            'member_username': 'self.username'
        }
    )

    class Meta:
        model = get_user_model()
        fields = (
            '@id', 'username', 'team'
        )

this will return:

{
   @id: {
     stream: 'user',
     payload: {
       action: 'retrieve',
       pk: 1023
      }
   },
   username: 'bob@example.com',
   team: {
     stream: 'team',
     payload: {
       action: 'retrieve',
       member_username: 'bob@example.com'
     }
   }
}

If you reference a Many field the HyperChannelsApiModelSerializer will do some magic so that:

class UserSerializer(HyperChannelsApiModelSerializer):
    friends = HyperChannelsApiRelationField(
        source='profile.friends'
    )

    class Meta:
        model = get_user_model()
        fields = (
            '@id', 'username', 'friends'
        )



        extra_kwargs = {
            'friends': {
                'kwarg_mappings': {
                    'user_pk': 'self.user.pk',
                }
            },
        }

Adding extra_kwargs for any Many field can be important so that you can controle the lookup params used.

NOTE all Many fields (forwards and backwards) will extract values from the parent instance regardless of if you use self. in the kwarg_mappings value.)

this will return:

{
   @id: {
     stream: 'user',
     payload: {
       action: 'retrieve',
       pk: 1023
      }
   },
   username: 'bob@example.com',
   friends: {
        stream: 'user_profile', payload: {action: 'list', user_pk: 1023}
    }
}

Remember you can also override the @id lookup/action and stream if needed, eg:

extra_kwargs = {
    '@id': {
        'action_name': 'subscribe_status',
        'kwarg_mappings': {
            'username': 'username'
        }
    },
}

Returning Many items.

Expect to get:

[
    {
     stream: 'user',
     payload: {
       action: 'retrieve',
       pk: 1023
      }
    },
    {
     stream: 'user',
     payload: {
       action: 'retrieve',
       pk: 234
      }
   },
    {
     stream: 'user',
     payload: {
       action: 'retrieve',
       pk: 103223
      }
   },
]

Rather than getting a fully expanded value for each instance you will rather just get a list of hyper media paths you can use to lookup the instance you need.

If you need to override the stream action or lookup do this:

class UserSerializer(HyperChannelsApiModelSerializer):

    class Meta:
        model = User
        fields = (
            '@id',
            'username'
        )

        many_stream_name = 'active_users'

        many_kwarg_mappings = {
            'username': 'username'
        }

        many_action_name = 'subscribe'

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hypermediachannels-0.0.5.tar.gz (8.1 kB view details)

Uploaded Source

Built Distribution

hypermediachannels-0.0.5-py2.py3-none-any.whl (6.9 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file hypermediachannels-0.0.5.tar.gz.

File metadata

  • Download URL: hypermediachannels-0.0.5.tar.gz
  • Upload date:
  • Size: 8.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.18.4 setuptools/40.1.0 requests-toolbelt/0.8.0 tqdm/4.23.4 CPython/3.6.3

File hashes

Hashes for hypermediachannels-0.0.5.tar.gz
Algorithm Hash digest
SHA256 c9dd26c206a4c194d07f88825cb777adce5186747f25acef8f41dc9cc1281e9f
MD5 480b76523579180ec876f2737893ec4b
BLAKE2b-256 4a4f9e8281d41b836a445bf281478f75c3c2e4e60d0fe0983e158c922d86045c

See more details on using hashes here.

File details

Details for the file hypermediachannels-0.0.5-py2.py3-none-any.whl.

File metadata

  • Download URL: hypermediachannels-0.0.5-py2.py3-none-any.whl
  • Upload date:
  • Size: 6.9 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.18.4 setuptools/40.1.0 requests-toolbelt/0.8.0 tqdm/4.23.4 CPython/3.6.3

File hashes

Hashes for hypermediachannels-0.0.5-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 00947fd56d0b5c12673b96fab97d37ec677d330f3ec8f70b5f1416c78cd26779
MD5 261f1a04c4b3eef7758bc320216f81a8
BLAKE2b-256 257ae5a42447d598e8df9beaafd0aa770b9b55eba602c32797898de732322263

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page