Giter VIP home page Giter VIP logo

channels-api's People

Contributors

crodriguez1a avatar destos avatar herst avatar linuxlewis avatar they4kman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

channels-api's Issues

Scaling

How would this package behave with, for e.g. 10 replicas of the same server? (both, rest and some websocket server). If a change goes to server 1, will it be received by a consumer which is listening on server 3?

when i try to send multiple create requests at the same time, it would simply miss some responses that i usually get back.

The socket channel-api works perfectly for one user at one point of time. But when i test it using a forloop, it would simply block the create request. So for the time being the only solution i could find is send one request and wait for 500 seconds. It's working now but i am worried about cases where many user will send create requests at the same point of time then it might miss few orders.

var i = 1;
function myLoop() {
setTimeout(function() {
var conn = new WebSocket('ws://54.238.247.144:5000/');
conn.onmessage = function(e) {
console.log(e.data);
};
var msg = {
stream: "ipad_orders",
payload: {
action: "create",
data: {
"unique_id": "123",
"push_token": "11",
"machine_id": 342,
"machine_name": "ok1",
"parlour": "parlour1",
"total_cost": 333,
"membership": false,
"delivered": false,
"items": "Hello" + i,
"qty": "1",
}
}
}
conn.onopen = () => conn.send(JSON.stringify(msg));
console.log("Sended" + i)
i++;
if (i < 10) {
myLoop();
}
}, 500)
}
myLoop();

RFE: Subscription to multiple actions at once

Might look like the following:

// get an event when any question is created, updated or deleted
var msg = {
  stream: "questions",
  payload: {
    action: "subscribe",
    data: {
      action: ["create", "update", "delete"]
    }
  }
}

DeleteModelMixin.delete returns 200 instead of 204

The destroy() method in the DestroyModelMixin for DRF returns HTTP_204_NO_CONTENT whereas the delete() method in DeleteModelMixin here returns 200. It seems this should be consistent and the 204 would be more correct. Am I missing something?

Error on ModelConsumerBase (0.1.4)

When installing the 0.1.4 version of channels_api I have an error in the dispatch method (generics.py line 31):

self.send(self.format_response(data=super().dispatch(message, **kwargs), message=message))

I change the line 31 by this:

self.send(self.format_response(data=super(ModelConsumerBase, self).dispatch(message, **kwargs), message=message))

And I worked OK

Query: Python 2.7?

I notice that channels-api requires Py3 to run according to its requirements.

I'm working on a project that may benefit from it, but the project is held into py2.7 stasis due to some remaining work that needs to be done getting twisted's telnet working on Py3.

So I'm thinking of making tweaks to this so it will run on Py2.7 for my own use.

Still learning the differences between Py3 and so I'm just making a simple question here: what specifically in this code does not work with Py2.7?

requirements.txt installs Channels 2.0

Currently running pip3 install -r requirements.txt installs Channels 2.0 which had a massive API overhaul and redesign that causes channels-api to be wholly incompatible. This is causing the current build to be reported as failed.

Why Custom permissions?

Since Django Rest Framework is a dependency, why are their permissions classes reimplemented and not just imported?

How to connect WebsocketDemultiplexer with pgpubsub

Hello, I was wondering if is there a way to connect from WebsocketDemultiplexer custome class to postgresql using pgpubsub?. I'm trying to broadcast postgres notifications through WebsocketDemultiplexer, or could you give one solution to achieve this please? I've noted WebsocketDemultiplexer has an own channel and it can't be used with websocket.receive in routing.py

I'm newbie using channels. Thanks in advanced.

Implament a PATCH ResourceBinding to enable Updating a single field

Hi there,
DRF supports HTTP PATCH methods, to support updating a particular part of an existing element. However, within channels-api, they is no such way of updating one field of an object.
Is it possible to create a new resource binding to implement functionality similar to the HTTP PATCH Method?

Incompatible with new Channels 1.0.2

Channels API is now incompatible with Channels 1.0.2, because of different number of parameters passed to group_names() method. Bug is reproduced by Channels API example. Reproduction:

  1. Upgrade Channels to 1.0.2
  2. Go to Django Admin and try to create a new instance of some model
  3. Channels crashes

Additionally, downgrading Channels to 1.0.1 solves the problem.

Django REST token authentication

Hi,

I'm trying to implement authentication using tokens generated by django-rest-framework.

Using this gist: https://gist.github.com/leonardoo/9574251b3c7eefccd84fc38905110ce4

I've managed to do this:

Consumer

class APIDemultiplexer(RestTokenConsumerMixin, WebsocketDemultiplexer):
    rest_user = True

    def connect(self, message, **kwargs):
        Group('users').add(message.reply_channel)

        # user here is correct instance of User from given token
        print(message.user)
        Group('users').send({
            'text': json.dumps({
                "accepted": "True",
            })
        })
    consumers = {
        'campaigns': CampaignBinding.consumer
    }

Resource binding

class CampaignBinding(ResourceBinding):

    model = Campaign
    stream = "campaigns"
    serializer_class = CampaignSerializer
    queryset = Campaign.objects.all()
    permission_classes = (AllowAny,)
   
    def get_serializer_context(self):
        # user here is Anonymous
        print(self.user)
        # I need user instance inside self.message
        return {'request': self.message}

My request
ws://localhost:8000/?token=ef0ef25fcfc75c0db91bbbccc062f0ab5786dc34

The thing is that I can access User instance only inside Consumer and User instance is not propagated to ResourceBinding. Is there some obvious way to access ser from token inside ResourceBinding?

Any help would be appreciated.

python 2.7

does it work with py2.7? Or i have to upgrade to py3?

Token based Auth

Hi all,

First thanks for this package. It's very much appreciated.

Second, I don't seem to be able to figure out the best way to go about authentication for clients using DRF token based auth. (Django OAuth Toolkit)

Any resource I've found on auth seems to focus on session based auth which I guess makes sense from a websocket point of view.

For my REST api I am sending an Authorization header with an access token as the value. What would you recommend I look into to get this auth working with the channels_api ?

Thank you

Permission pk field useless

Currently when making custom permissions, the "pk" field is useless as there is no way to actually retrieve the instance of the object you are checking against as the BasePermission class has no referent to a model type.

I ran into this issue when trying to write the following permission class to see if a user owns a model:

class IsOwner(BasePermission):
    def has_permission(self, user, action, pk):
        try:
            # have to hard code Job here because BasePermission has no reference to the Model it is checking
            job = Job.objects.get(pk=pk) 
        except Job.DoesNotExist:
            return False

        if action == "SUBSCRIBE":
            return user == job.owner
        return False

While this works for the Job model, I want to make this more general as I have other models with Owner that I want to use the same permission on. As I see it now, there's no way to generically use this field to do anything at all.

I think this was just a design oversight and I figure this can be solved pretty easily through just passing a reference to the Model of the binding to the permission class upon construction that can then be accessed from the has_permission method. I'll submit a PR with a fix once I have a chance.

Permissions

Great work man! Any progress / thoughts on permissions? From that point forward it will become useful for me.

Create a subscription via model fields

Hi there,
Currently, the subscriptions only allow subscriptions for any resource, or a specific resource by it's PK. Is it possible to implement functionally to subscribe to a set of resources that fulfil some criteria, other than PK.
For example, we might have a field called name, and we may want to subscribe to any creations in which the name == "John". The current work around is to subscribe for all creations, and then filter the stream client side.
Just an example of how this could be done
{
"stream": "people",
"payload": {
"action":"subscribe",
"data": {
"action": "create"
}
"filter":{
"name": "John"
}
}

It would probably also make sense to move the existing PK field to the new filter dict.

This is obviously a big design change, but I personally feel that keeping as much of the processing on the server side is better than the current workaround.

Permissions: has_permission() takes 3 positional arguments but 4 were given

I am getting this error after I updated the package

2017-06-01 02:16:22,002 - ERROR - worker - Error processing message with consumer faceoff_api.routing.APIDemultiplexer:
Traceback (most recent call last):
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/worker.py", line 119, in run
    consumer(message, **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/generic/base.py", line 32, in __init__
    self.dispatch(message, **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/generic/base.py", line 70, in dispatch
    return self.get_handler(message, **kwargs)(message, **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/generic/websockets.py", line 154, in raw_receive
    self.receive(self.decode_json(message['text']), **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/generic/websockets.py", line 266, in receive
    consumer(self.message, **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/binding/base.py", line 240, in consumer
    handler(message, **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/sessions.py", line 78, in inner
    return func(*args, **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/auth.py", line 42, in inner
    return func(message, *args, **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/binding/websockets.py", line 90, in trigger_inbound
    super(WebsocketBinding, cls).trigger_inbound(message, **kwargs)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels/binding/base.py", line 222, in trigger_inbound
    self.run_action(self.action, self.pk, self.data)
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels_api/bindings.py", line 145, in run_action
    if not self.has_permission(self.user, action, pk):
  File "/Users/coreytrombley/.envs/faceoff_venv/lib/python3.5/site-packages/channels_api/bindings.py", line 111, in has_permission
    if not cls().has_permission(user, action, pk):
TypeError: has_permission() takes 3 positional arguments but 4 were given

Authorization based on JWT, how can i get works?

Hi, linuxlewis.

I think it's question to you ..

I have the trouble with authorization based on this package:

https://github.com/GetBlimp/django-rest-framework-jwt

If i try to do normal ajax request to collection /questions i get errors:

HyperlinkedIdentityField requires the request in the serializer context. Add context={'request': request} when instantiating the serializer.

So .. ok. That's can be good for me, i would change all application logic for use websockets and it's not problem for me.

But when i try to send request with ws.send(JSON.stringify(msg)):

var msg = { stream: "questions", payload: { action: "create", data: { description: "What is your favorite python package?", categories: ["http://localhost:8000/api/categories/1/"] }, request_id: "some-guid" } } ws.send(JSON.stringify(msg))

I get this error:

IntegrityError: null value in column "owner_id" violates not-null constraint
DETAIL: Failing row contains (11, 2017-06-11 12:06:02.583387+00, What is your favorite python package?, , 1200.00000000, f, f, f, null).

My QuestionSerializer looks like:

`class QuestionSerializer(serializers.HyperlinkedModelSerializer):

def create(self, validated_data):

    categories_data = validated_data.pop('categories')

    question = Question.objects.create(**validated_data)

    question.is_open = True
    question.is_finish = True
    question.save()

    for category in categories_data:
        question.categories.add(category)

    return question

owner = UserSerializer(read_only=True)
answers = AnswerSerializer(many=True, read_only=True)
elo = serializers.ReadOnlyField()
is_verified = serializers.ReadOnlyField()
is_finish = serializers.ReadOnlyField()
is_open = serializers.ReadOnlyField()

class Meta:
    model = Question
    fields = (
        'url',
        'id',
        'created',
        'owner',
        'description',
        'elo',
        'is_verified',
        'is_finish',
        'is_open',
        'categories',
        'answers'
    )`

The model:

`class Question(models.Model):

created = models.DateTimeField(auto_now_add=True)

owner = models.ForeignKey(
    'auth.User',
    related_name='%(app_label)s_%(class)s_related'
)

categories = models.ManyToManyField(
    'core.Category'
)

answers = models.ManyToManyField(
    'learn.Answer'
)

description = models.TextField()

additional = models.TextField()

elo = models.DecimalField(
    max_digits=20,
    decimal_places=8,
    default=Decimal('1200.0000')
)

is_verified = models.BooleanField(
    default=False
)

is_finish = models.BooleanField(
    default=False
)

is_open = models.BooleanField(
    default=False,
    blank=True
)

def __unicode__(self):
    return self.description`

And view:

`class QuestionViewSet(viewsets.ModelViewSet):

serializer_class = QuestionSerializer
permissions_classes = (
    IsOwnerOrReadOnly,
)

def get_queryset(self):

    queryset = Question.objects.all()

    category = self.request.query_params.get('category', None)
    description = self.request.query_params.get('description', None)

    if description is not None:
        queryset = Question.objects.filter(description__icontains=description)

    if category is not None and description is None:

        is_verified = self.request.query_params.get('is_verified', None)
        is_finish = self.request.query_params.get('is_finish', None)

        if is_verified is not None and is_finish is not None:
            queryset = Question.objects.filter(categories__pk=category, is_verified=True, is_finish=True)
        else:
            queryset = Question.objects.filter(categories__pk=category)

    if category is not None and description is not None:
        queryset = Question.objects.filter(categories__pk=category, description=description)

    return queryset

def perform_create(self, serializer):
    serializer.save(owner=self.request.user)`

Can you explain me how can i get it works all together?

Basicly i need to create only private chat for this moment for my users but i trying to understand how can i make other stuff in application with channels_api and this crap won't let me fall a sleep...

Thank you for your attention and suggestion if you know how i can resolve this problem.

Pypi module missing decorators

Hi All, I installed the package through pip and it seems to be missing the decorator module.

python3.4/site-packages/channels_api contains; bindings.py, mixins.py, settings.py, urs.py etc but no decorators.py

env; python 3.4, django 1.11, DRF 3.6

Problems with custom primary keys

If you don't use the default django primary key for your models and instead use "ID = models.AutoField(primary_key=True)" for example there are two problems.

Firstly id = instance.id in the bindings.py will throw an error because you don't have the id field. Can apparently be fixed by replacing it with id = instance.pk

Secondly if you send a "create" message through a websocket it will complain that the field "ID" is required.

Documentation for subscriptions possibly wrong?

Are you sure that the following

// get an event when question(1) is updated
var msg = {
  stream: "questions",
  payload: {
    action: "subscribe"
    data: {
      action: "update",
      pk: "1"
    }
  }
}

shouldn't be

// get an event when question(1) is updated
var msg = {
  stream: "questions",
  payload: {
    action: "subscribe",
    pk: "1",
    data: {
      action: "update"
    }
  }
}

instead? (BTW, there is also a syntax error.)

From our testing this seems to be the case.

Channels 2.0 support

Since channels project dropped Bindings from base package due it's simplistic design - this is a great opportunity to implement them within this project and keep this project relevant.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.