skip to Main Content

I have a django app based on this tutorial that works perfectly. It uses Redis in the Channel layers

 CHANNEL_LAYERS = {
    'default': {
       'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],
     },
 },

}

The problem I have is that my web hosting provider will not allow Redis (unless I pay ££££).

Every example that I can find uses Redis in this role. Is there an alternative I could use?

2

Answers


  1. Chosen as BEST ANSWER

    It turned out that channels is a non-starter on an affordable web-hosting platform. So I reverted to using Ajax and long polling. My application is based on this Django Tutorial.

    models.py

    class Message(models.Model):
        room_name = models.CharField(null=False, blank=False, max_length=50)
        sender = models.CharField(null=False, blank=False, max_length=50, default='Sender username')
        datetime = models.DateTimeField(null=True, auto_now_add=True)
        type = models.IntegerField(null=True, blank=True)
        text = models.CharField(null=False, blank=False, max_length=250, default='message text')
        context = models.TextField(null=True, blank=True)
    

    urls.py

    urlpatterns = [
        path('<str:partner_pk>/check-message', views.CheckMessage.as_view(), name="check-message"),
        path('<str:partner_pk>/send-message/<str:chat_text>', views.SendMessage.as_view(), name="send-message"),
    ]
    

    views.py

    class CheckMessage(View):
        """Duo check message."""
    
        def get(self, request, partner_pk):
            """Render the GET request."""
            pair, room_name = sort_pair(partner_pk, request.user.pk)
            partner = User.objects.get(pk=partner_pk)
            profile = get_object_or_404(Profile, user=request.user)
            message = Message.objects.filter(room_name=room_name, sender=partner.username).earliest('datetime')
            context = {'type': -1}
            context = json.loads(message.context)
            context['sender'] = message.sender
            context['datetime'] = message.datetime
            context['message_type'] = message.type
            context['text'] = message.text
            context['seat'] = profile.seat
            message.delete()
            return JsonResponse(context, safe=False)
    
    class SendMessage(View):
        def get(self, request, partner_pk, chat_text):
            message_type = app.MESSAGE_TYPES['chat']
            send_message(request, partner_pk, message_type, text=chat_text, context={})
            return JsonResponse({}, safe=False)
    

    chat.js

    window.setInterval(checkMessage, 3000);
    
    function checkMessage () {
        $.ajax(
            {
            type:"GET",
            url: "check-message",
            cache: false,
            success: function(message) {
                processMessage(message);
                }
            }
        )    
    }
    
    // Take action when a message is received
    function processMessage(context) {
        switch (context.message_type) {
            case 0:
                sendMessage(context)
                functionOne()
                break;
            case 1:
                sendMessage(context)
                functionTwo()
                break;
            case 2:
                sendMessage(context)
                functionThree()
                break;
        }
    }
    
    // Send a message to chat   
    function sendMessage (context) {
        if (context.sender != username) {
            var messageObject = {
                    'username': context.sender,
                    'text': context.text,
                };
            displayChat(context);
    
            }
    }    
    
    // Display a chat message in the chat box.
    function displayChat(context) {
        if (context.text !== '') {
            var today = new Date();
            var hours = pad(today.getHours(), 2)
            var minutes = pad(today.getMinutes(), 2)
            var seconds = pad(today.getSeconds(), 2)
            var time = hours + ":" + minutes + ":" + seconds;
            var chat_log = document.getElementById("chat-log");
            chat_log.value += ('('+time+') '+context.sender + ': ' + context.text + 'n');
            chat_log.scrollTop = chat_log.scrollHeight;
        }
    }
    
    //pad string with leading zeros
    function pad(num, size) {
        var s = num+"";
        while (s.length < size) s = "0" + s;
        return s;
    }
    
    // Call submit chat message if the user presses <return>.
    document.querySelector('#chat-message-input').focus();
    document.querySelector('#chat-message-input').onkeyup = function (e) {
        if (e.keyCode === 13) {  // enter, return
            document.querySelector('#chat-message-submit').click();
        }
    };
    
    // Submit the chat message if the user clicks on 'Send'.
    document.querySelector('#chat-message-submit').onclick = function (e) {
        var messageField = document.querySelector('#chat-message-input'), text = messageField.value,        chat_log = document.getElementById("chat-log");
        context = {sender: username, text: messageField.value}
        displayChat(context)
        sendChat(messageField.value)
        chat_log.scrollTop = chat_log.scrollHeight;
        messageField.value = '';
    };
    
    // Call the send-chat view
    function sendChat(chat_text) {
        $.ajax(
            {
            type:"GET",
            url: "send-message/"+chat_text,
            cache: false,
            }
        )    
    }
    

  2. there are a few options.

    1. you can run your channel layer on a different service to were the main instance runs. AWS ElastiCache or many other redis hosts out there.

    2. There is also a RabbitMQ channel layer but if your hosting provider charges a lot for reddis i expect they will also charge a lot for this … https://github.com/CJWorkbench/channels_rabbitmq/

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search